class SpreadsheetUtils {

    public static void logInfo(Report report, String message, SheetParser parser) {
        logIssue(report, new Issue(message, Issue.Level.INFO), parser);
    }

    public static void logWarning(Report report, String message, SheetParser parser) {
        logIssue(report, new Issue(message, Issue.Level.WARNING), parser);
    }

    public static void logError(Report report, String message, SheetParser parser) {
        logIssue(report, new Issue(message, Issue.Level.SEVERE), parser);
    }

    public static void logCritical(Report report, String message, SheetParser parser) {
        logIssue(report, new Issue(message, Issue.Level.CRITICAL), parser);
    }

    public static void logIssue(Report report, Issue issue, SheetParser parser) {
        if (parser != null) {
            String newMessage = "[" + NbBundle
                .getMessage(SpreadsheetUtils.class, "SpreadsheetUtils.recordNumber", parser.getCurrentRecordNumber()) +
                "] " + issue.getMessage();
            issue = new Issue(newMessage, issue.getLevel());
        }

        if (report != null) {
            report.logIssue(issue);
        } else {
            Level level;
            switch (issue.getLevel()) {
                case INFO:
                    level = Level.INFO;
                    break;
                case WARNING:
                    level = Level.WARNING;
                    break;
                case SEVERE:
                case CRITICAL:
                    level = Level.SEVERE;
                    break;
                default:
                    level = Level.FINE;
            }
            Logger.getLogger("").log(level, issue.getMessage());
        }
    }

    public static CSVParser configureCSVParser(File file, Character fieldSeparator, Charset charset,
                                               boolean withFirstRecordAsHeader) throws IOException {<FILL_FUNCTION_BODY>}
}

        if (fieldSeparator == null) {
            fieldSeparator = ',';
        }

        CSVFormat csvFormat = CSVFormat.DEFAULT
            .withDelimiter(fieldSeparator)
            .withEscape('\\')
            .withIgnoreEmptyLines(true)
            .withNullString("")
            .withIgnoreSurroundingSpaces(true)
            .withTrim(true);

        if (withFirstRecordAsHeader) {
            csvFormat = csvFormat
                .withFirstRecordAsHeader()
                .withAllowMissingColumnNames(false)
                .withIgnoreHeaderCase(false);
        } else {
            csvFormat = csvFormat.withHeader((String[]) null).withSkipHeaderRecord(false);
        }

        boolean hasBOM = false;
        try (FileInputStream is = new FileInputStream(file)) {
            CharsetToolkit charsetToolkit = new CharsetToolkit(is);
            hasBOM = charsetToolkit.hasUTF8Bom() || charsetToolkit.hasUTF16BEBom() || charsetToolkit.hasUTF16LEBom();
        } catch (IOException e) {
            //NOOP
        }

        FileInputStream fileInputStream = new FileInputStream(file);
        InputStreamReader is = new InputStreamReader(fileInputStream, charset);
        if (hasBOM) {
            try {
                is.read();
            } catch (IOException e) {
                // should never happen, as a file with no content
                // but with a BOM has at least one char
            }
        }
        return new CSVParser(is, csvFormat);
    
<no_super_class>