private <T extends Position> ValueWithFailures<List<T>> parseFile(CharSource charSource, Class<T> positionType) { try (CsvIterator csv = CsvIterator.of(charSource, true)) { if (!csv.headers().contains(TYPE_FIELD)) { return ValueWithFailures.of( ImmutableList.of(), FailureItem.of(FailureReason.PARSING, "CSV file does not contain '{header}' header: {}", TYPE_FIELD, charSource)); } return parseFile(csv, positionType); } catch (RuntimeException ex) { return ValueWithFailures.of( ImmutableList.of(), FailureItem.of( FailureReason.PARSING, ex, "CSV file could not be parsed: {exceptionMessage}: {}", ex.getMessage(), charSource)); } }
/** * Parses one or more CSV format position files. * <p> * A type is specified to filter the positions. * If the type is {@link SecurityPosition}, then ETD parsing will proceed as per {@link #parseLightweight(Collection)}. * Otherwise, ETD parsing will proceed as per {@link #parse(Collection)}. * <p> * CSV files sometimes contain a Unicode Byte Order Mark. * Callers are responsible for handling this, such as by using {@link UnicodeBom}. * * @param <T> the position type * @param charSources the CSV character sources * @param positionType the position type to return * @return the loaded positions, all errors are captured in the result */ public <T extends Position> ValueWithFailures<List<T>> parse(Collection<CharSource> charSources, Class<T> positionType) { try { ValueWithFailures<List<T>> result = ValueWithFailures.of(ImmutableList.of()); for (CharSource charSource : charSources) { ValueWithFailures<List<T>> singleResult = parseFile(charSource, positionType); result = result.combinedWith(singleResult, Guavate::concatToList); } return result; } catch (RuntimeException ex) { return ValueWithFailures.of(ImmutableList.of(), FailureItem.of(FailureReason.ERROR, ex)); } }