| 1 | /* | |
| 2 | * Copyright 2004 the original author or authors. | |
| 3 | * | |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
| 5 | * you may not use this file except in compliance with the License. | |
| 6 | * You may obtain a copy of the License at | |
| 7 | * | |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 9 | * | |
| 10 | * Unless required by applicable law or agreed to in writing, software | |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 | * See the License for the specific language governing permissions and | |
| 14 | * limitations under the License. | |
| 15 | */ | |
| 16 | package com.ancientprogramming.fixedformat4j.io.read; | |
| 17 | ||
| 18 | import com.ancientprogramming.fixedformat4j.exception.FixedFormatException; | |
| 19 | import org.slf4j.Logger; | |
| 20 | import org.slf4j.LoggerFactory; | |
| 21 | ||
| 22 | /** | |
| 23 | * Strategy invoked when a matched line fails to parse into a record object. | |
| 24 | * | |
| 25 | * <p>Implement this interface to define custom error handling — for example, collecting | |
| 26 | * failed lines for a post-processing error report. Two built-in strategies are provided as | |
| 27 | * static factory methods: {@link #throwException()} and {@link #skipAndLog()}.</p> | |
| 28 | * | |
| 29 | * <p>Because this is a {@link FunctionalInterface}, a lambda can be passed wherever a | |
| 30 | * {@code ParseErrorStrategy} is expected:</p> | |
| 31 | * <pre>{@code | |
| 32 | * .parseErrorStrategy((wrapped, line, lineNumber) -> | |
| 33 | * errorList.add("Line " + lineNumber + ": " + wrapped.getMessage())) | |
| 34 | * }</pre> | |
| 35 | * | |
| 36 | * <p>To abort processing on error, throw from the lambda. To skip the line, return normally.</p> | |
| 37 | * | |
| 38 | * @author Jacob von Eyben - <a href="https://eybenconsult.com">https://eybenconsult.com</a> | |
| 39 | * @since 1.8.0 | |
| 40 | */ | |
| 41 | @FunctionalInterface | |
| 42 | public interface ParseErrorStrategy { | |
| 43 | ||
| 44 | Logger LOG = LoggerFactory.getLogger(ParseErrorStrategy.class); | |
| 45 | ||
| 46 | /** | |
| 47 | * Handles a line that matched a pattern but could not be parsed into a record object. | |
| 48 | * | |
| 49 | * <p>Throw a {@link FixedFormatException} to abort processing, or return normally to | |
| 50 | * skip the record and continue with the next line.</p> | |
| 51 | * | |
| 52 | * @param wrapped a {@link FixedFormatException} wrapping the original parse failure; | |
| 53 | * the exception message includes the line number | |
| 54 | * @param line the raw content of the line, without any trailing line-ending characters | |
| 55 | * @param lineNumber the 1-based line number within the source being read | |
| 56 | */ | |
| 57 | void handle(FixedFormatException wrapped, String line, long lineNumber); | |
| 58 | ||
| 59 | /** | |
| 60 | * Returns a strategy that rethrows the parse exception immediately (fail-fast). | |
| 61 | * | |
| 62 | * @return a fail-fast strategy; never {@code null} | |
| 63 | */ | |
| 64 | static ParseErrorStrategy throwException() { | |
| 65 |
1
1. throwException : replaced return value with null for com/ancientprogramming/fixedformat4j/io/read/ParseErrorStrategy::throwException → KILLED |
return (wrapped, line, lineNumber) -> { throw wrapped; }; |
| 66 | } | |
| 67 | ||
| 68 | /** | |
| 69 | * Returns a strategy that skips the line and logs details at WARN level via SLF4J. | |
| 70 | * Processing continues with the next line. | |
| 71 | * | |
| 72 | * <p><strong>Note:</strong> logging only occurs if an SLF4J binding is present on the | |
| 73 | * classpath at runtime. If no binding is configured, the warning is silently discarded. | |
| 74 | * When guaranteed error visibility is required, use a custom lambda strategy instead.</p> | |
| 75 | * | |
| 76 | * @return a skip-and-log strategy; never {@code null} | |
| 77 | */ | |
| 78 | static ParseErrorStrategy skipAndLog() { | |
| 79 |
1
1. skipAndLog : replaced return value with null for com/ancientprogramming/fixedformat4j/io/read/ParseErrorStrategy::skipAndLog → KILLED |
return (wrapped, line, lineNumber) -> |
| 80 | LOG.warn("Skipping line {}: {} — {}", lineNumber, line, | |
| 81 |
7
1. lambda$skipAndLog$1 : removed conditional - replaced equality check with false → KILLED 2. lambda$skipAndLog$1 : removed call to com/ancientprogramming/fixedformat4j/exception/FixedFormatException::getMessage → KILLED 3. lambda$skipAndLog$1 : negated conditional → KILLED 4. lambda$skipAndLog$1 : removed call to com/ancientprogramming/fixedformat4j/exception/FixedFormatException::getCause → KILLED 5. lambda$skipAndLog$1 : removed call to java/lang/Throwable::getMessage → KILLED 6. lambda$skipAndLog$1 : removed call to com/ancientprogramming/fixedformat4j/exception/FixedFormatException::getCause → KILLED 7. lambda$skipAndLog$1 : removed conditional - replaced equality check with true → KILLED |
wrapped.getCause() != null ? wrapped.getCause().getMessage() : wrapped.getMessage()); |
| 82 | } | |
| 83 | } | |
Mutations | ||
| 65 |
1.1 |
|
| 79 |
1.1 |
|
| 81 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |