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

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

package cdc.impex.core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cdc.impex.imports.ImportIssue;
import cdc.impex.imports.ImportIssueType;
import cdc.impex.imports.ImportRow;
import cdc.impex.templates.ColumnTemplate;
import cdc.impex.templates.ImportAction;
import cdc.impex.templates.SheetTemplate;
import cdc.issues.IssueSeverity;
import cdc.issues.locations.WorkbookLocation;
import cdc.util.lang.Checks;

public final class ImportRowImpl implements ImportRow {
    private static final String ERASE = "ERASE";
    private final String systemId;
    private final SheetTemplate template;
    private final String sheetName;
    private final int number;
    private final Map rawData;
    private final Map data = new HashMap<>();
    private List issues = null;

    private ImportRowImpl(String systemId,
                          SheetTemplate template,
                          String sheetName,
                          int number,
                          Map rawData) {
        this.systemId = systemId;
        this.template = Checks.isNotNull(template, "template");
        this.sheetName = sheetName;
        this.number = number;
        this.rawData = new HashMap<>(rawData);

        // Read raw data, convert it, check it, and put converted result into data
        for (final Map.Entry entry : rawData.entrySet()) {
            // Retrieve column name
            final String name = entry.getKey();
            if (template.containsColumn(name)) {
                // Retrieve associated column template
                final ColumnTemplate column = template.getColumn(name);
                Object value;
                if (ERASE.equals(entry.getValue())) {
                    value = ERASE;
                } else {
                    // Convert raw data
                    try {
                        value = column.getImportConverter().apply(entry.getValue());
                    } catch (final RuntimeException e) {
                        // Conversion failed
                        addIssue(ImportIssueType.NON_CONVERTIBLE_DATA,
                                 "Failed to convert '" + entry.getValue() + "' to " + column.getDataType().getCanonicalName() + ".",
                                 column);
                        value = null;
                    }
                }

                // Check converted data
                if (value != null && value != ERASE && column.getCheckerOrNull() != null) {
                    final boolean valid = column.getCheckerOrNull().testRaw(value);
                    if (!valid) {
                        // Check failed
                        addIssue(ImportIssueType.NON_COMPLIANT_DATA,
                                 column.getCheckFailureSeverity(),
                                 "Check [" + column.getCheckerOrNull().explain(true, "?") + "] failed for '?'=" + value + ".",
                                 column);
                    }
                }
                // Put converted data, even if check failed
                if (value != null) {
                    this.data.put(name, value);
                }
            }
        }

        final ImportAction action = getAction();

        // Check that columns are set / unset
        // If action is not correctly set, this may be incomplete
        for (final ColumnTemplate column : template.getColumns()) {
            final Object value = this.data.get(column.getName());
            if (column.getUsage().isMandatoryFor(getAction())) {
                // Column is mandatory
                if (value == null) {
                    addIssue(ImportIssueType.MISSING_MANDATORY_DATA,
                             "No data for mandatory column '" + column.getName() + "'.",
                             column);
                } else if (value == ERASE) {
                    addIssue(ImportIssueType.UNEXPECTED_ERASE,
                             "Unexpected " + ERASE + " in mandatory column '" + column.getName() + "' when action is " + action
                                     + ".",
                             column);
                }
            } else {
                // Column is optional
                if (value == ERASE) {
                    if (action == ImportAction.CREATE || action == ImportAction.DELETE) {
                        addIssue(ImportIssueType.UNEXPECTED_ERASE,
                                 "Unexpected " + ERASE + " in optional column '" + column.getName() + "' when action is " + action
                                         + ".",
                                 column);
                    }
                } else if (value != null && action == ImportAction.DELETE && !template.isActionColumn(column)) {
                    addIssue(ImportIssueType.UNEXPECTED_DATA,
                             "Unexpected data in optional column '" + column.getName() + "' when action is " + action + ".",
                             column);
                }
            }
        }
    }

    private void addIssue(ImportIssueType type,
                          IssueSeverity severity,
                          String description,
                          ColumnTemplate column) {
        if (issues == null) {
            issues = new ArrayList<>();
        }
        issues.add(ImportIssue.builder()
                              .name(type)
                              .severity(severity)
                              .description(description)
                              .addLocation(WorkbookLocation.builder()
                                                           .sheetName(sheetName == null ? template.getName() : sheetName)
                                                           .columnName(column.getName())
                                                           .rowNumber(number)
                                                           .systemId(systemId)
                                                           .build())
                              .build());
    }

    private void addIssue(ImportIssueType type,
                          String description,
                          ColumnTemplate column) {
        addIssue(type,
                 type.getSeverity(),
                 description,
                 column);
    }

    @Override
    public String getSystemId() {
        return systemId;
    }

    @Override
    public SheetTemplate getTemplate() {
        return template;
    }

    @Override
    public int getNumber() {
        return number;
    }

    @Override
    public ImportAction getAction() {
        return getDataOrNull(ImportAction.class,
                             template.getActionColumnName());
    }

    @Override
    public boolean isErase(String name) {
        return data.get(name) == ERASE;
    }

    @Override
    public String getRawDataOrNull(String name) {
        return rawData.get(name);
    }

    @Override
    public Object getDataOrNull(String name) {
        final Object value = data.get(name);
        return value == ERASE ? null : value;
    }

    @Override
    public  T getDataOrNull(Class cls,
                               String name) {
        return cls.cast(getDataOrNull(name));
    }

    @Override
    public List getIssues() {
        return issues == null
                ? Collections.emptyList()
                : issues;
    }

    @Override
    public boolean canBeProcessed() {
        if (issues == null) {
            return true;
        } else {
            for (final ImportIssue issue : issues) {
                if (issue.getSeverity().isAtLeast(IssueSeverity.CRITICAL)) {
                    return false;
                }
            }
            return true;
        }
    }

    @Override
    public boolean isEmpty() {
        return data.isEmpty();
    }

    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        builder.append("[")
               .append(getNumber())
               .append(" {");
        boolean first = true;
        for (final String name : template.getColumnNames()) {
            if (first) {
                first = false;
            } else {
                builder.append(", ");
            }
            builder.append(name)
                   .append("=")
                   .append(getDataOrNull(name));
        }
        builder.append("}]");
        return builder.toString();
    }

    public static Builder builder() {
        return new Builder();
    }

    public static final class Builder {
        private String systemId;
        private SheetTemplate template;
        private String sheetName;
        private int number;
        private final Map data = new HashMap<>();

        private Builder() {
        }

        public Builder systemId(String systemId) {
            this.systemId = systemId;
            return this;
        }

        public Builder template(SheetTemplate template) {
            this.template = template;
            return this;
        }

        public Builder sheetName(String sheetName) {
            this.sheetName = sheetName;
            return this;
        }

        public Builder number(int number) {
            this.number = number;
            return this;
        }

        public Builder put(String name,
                           String value) {
            this.data.put(name, value);
            return this;
        }

        public ImportRow build() {
            return new ImportRowImpl(systemId,
                                     template,
                                     sheetName,
                                     number,
                                     data);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy