|
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
|
|
|
|
20
|
|
import java.util.List; |
|
21
|
|
import java.util.stream.Collectors; |
|
22
|
|
|
|
23
|
|
import static java.lang.String.format; |
|
24
|
|
|
|
25
|
|
/** |
|
26
|
|
* Strategy that decides which mappings to use when more than one |
|
27
|
|
* {@link RecordMapping} matches the same line. |
|
28
|
|
* |
|
29
|
|
* <p>The {@code matched} list passed to {@link #resolve} is ordered "most detailed first, |
|
30
|
|
* then registration order" — depth equals the number of positions declared by a |
|
31
|
|
* {@link LinePattern}, and {@link LinePattern#matchAll()} therefore appears last among |
|
32
|
|
* matches.</p> |
|
33
|
|
* |
|
34
|
|
* <p>Three built-in strategies are provided as static factory methods: |
|
35
|
|
* {@link #firstMatch()}, {@link #throwOnAmbiguity()}, and {@link #allMatches()}.</p> |
|
36
|
|
* |
|
37
|
|
* <p>Implement this interface to define custom multi-match logic — for example, choosing |
|
38
|
|
* the mapping whose {@code @Record} length most closely matches the actual line length.</p> |
|
39
|
|
* |
|
40
|
|
* @author Jacob von Eyben - <a href="https://eybenconsult.com">https://eybenconsult.com</a> |
|
41
|
|
* @since 1.8.0 |
|
42
|
|
*/ |
|
43
|
|
@FunctionalInterface |
|
44
|
|
public interface MultiMatchStrategy { |
|
45
|
|
|
|
46
|
|
/** |
|
47
|
|
* Resolves which mappings should be used to parse a line that matched more than one pattern. |
|
48
|
|
* Not invoked when only one mapping matches — single matches bypass this strategy entirely. |
|
49
|
|
* |
|
50
|
|
* @param matched all mappings whose pattern matched the line; size is always > 1 |
|
51
|
|
* @param lineNumber the 1-based line number |
|
52
|
|
* @return the subset of {@code matched} to use for parsing; may be empty to skip the line; |
|
53
|
|
* never {@code null} |
|
54
|
|
*/ |
|
55
|
|
List<RecordMapping<?>> resolve(List<RecordMapping<?>> matched, long lineNumber); |
|
56
|
|
|
|
57
|
|
/** |
|
58
|
|
* Returns a strategy that uses the most detailed matching mapping and ignores the rest. |
|
59
|
|
* Ties (mappings with equal depth) are broken by registration order. This is the default |
|
60
|
|
* strategy used by {@link FixedFormatReader}. |
|
61
|
|
* |
|
62
|
|
* @return a first-match strategy; never {@code null} |
|
63
|
|
*/ |
|
64
|
|
static MultiMatchStrategy firstMatch() { |
|
65
|
6
1. firstMatch : replaced return value with null for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::firstMatch → KILLED
2. lambda$firstMatch$0 : Substituted 0 with 1 → KILLED
3. lambda$firstMatch$0 : replaced call to java/util/List::subList with receiver → KILLED
4. lambda$firstMatch$0 : replaced return value with Collections.emptyList for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::lambda$firstMatch$0 → KILLED
5. lambda$firstMatch$0 : Substituted 1 with 0 → KILLED
6. lambda$firstMatch$0 : removed call to java/util/List::subList → KILLED
|
return (matched, lineNumber) -> matched.subList(0, 1); |
|
66
|
|
} |
|
67
|
|
|
|
68
|
|
/** |
|
69
|
|
* Returns a strategy that throws {@link FixedFormatException} if more than one pattern |
|
70
|
|
* matches, including the line number and all matching class names in the exception message. |
|
71
|
|
* |
|
72
|
|
* @return a throw-on-ambiguity strategy; never {@code null} |
|
73
|
|
*/ |
|
74
|
|
static MultiMatchStrategy throwOnAmbiguity() { |
|
75
|
1
1. throwOnAmbiguity : replaced return value with null for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::throwOnAmbiguity → KILLED
|
return (matched, lineNumber) -> { |
|
76
|
6
1. lambda$throwOnAmbiguity$2 : changed conditional boundary → SURVIVED
2. lambda$throwOnAmbiguity$2 : removed conditional - replaced comparison check with true → SURVIVED
3. lambda$throwOnAmbiguity$2 : Substituted 1 with 0 → SURVIVED
4. lambda$throwOnAmbiguity$2 : removed conditional - replaced comparison check with false → KILLED
5. lambda$throwOnAmbiguity$2 : negated conditional → KILLED
6. lambda$throwOnAmbiguity$2 : removed call to java/util/List::size → KILLED
|
if (matched.size() > 1) { |
|
77
|
1
1. lambda$throwOnAmbiguity$2 : removed call to java/util/List::stream → KILLED
|
String classes = matched.stream() |
|
78
|
5
1. lambda$throwOnAmbiguity$2 : removed call to java/util/stream/Stream::map → KILLED
2. lambda$throwOnAmbiguity$1 : removed call to com/ancientprogramming/fixedformat4j/io/read/RecordMapping::getRecordClass → KILLED
3. lambda$throwOnAmbiguity$2 : replaced call to java/util/stream/Stream::map with receiver → KILLED
4. lambda$throwOnAmbiguity$1 : replaced return value with "" for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::lambda$throwOnAmbiguity$1 → KILLED
5. lambda$throwOnAmbiguity$1 : removed call to java/lang/Class::getSimpleName → KILLED
|
.map(m -> m.getRecordClass().getSimpleName()) |
|
79
|
2
1. lambda$throwOnAmbiguity$2 : removed call to java/util/stream/Collectors::joining → KILLED
2. lambda$throwOnAmbiguity$2 : removed call to java/util/stream/Stream::collect → KILLED
|
.collect(Collectors.joining(", ")); |
|
80
|
2
1. lambda$throwOnAmbiguity$2 : Substituted 2 with 3 → SURVIVED
2. lambda$throwOnAmbiguity$2 : Substituted 0 with 1 → KILLED
|
throw new FixedFormatException( |
|
81
|
5
1. lambda$throwOnAmbiguity$2 : replaced call to java/lang/String::format with argument → KILLED
2. lambda$throwOnAmbiguity$2 : Substituted 1 with 0 → KILLED
3. lambda$throwOnAmbiguity$2 : removed call to com/ancientprogramming/fixedformat4j/exception/FixedFormatException::<init> → KILLED
4. lambda$throwOnAmbiguity$2 : removed call to java/lang/Long::valueOf → KILLED
5. lambda$throwOnAmbiguity$2 : removed call to java/lang/String::format → KILLED
|
format("Line %d matched multiple patterns: %s", lineNumber, classes)); |
|
82
|
|
} |
|
83
|
1
1. lambda$throwOnAmbiguity$2 : replaced return value with Collections.emptyList for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::lambda$throwOnAmbiguity$2 → NO_COVERAGE
|
return matched; |
|
84
|
|
}; |
|
85
|
|
} |
|
86
|
|
|
|
87
|
|
/** |
|
88
|
|
* Returns a strategy that loads the line once per matching mapping and emits one record |
|
89
|
|
* object per match, ordered most detailed first with registration order as the tiebreaker. |
|
90
|
|
* |
|
91
|
|
* @return an all-matches strategy; never {@code null} |
|
92
|
|
*/ |
|
93
|
|
static MultiMatchStrategy allMatches() { |
|
94
|
2
1. lambda$allMatches$3 : replaced return value with Collections.emptyList for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::lambda$allMatches$3 → KILLED
2. allMatches : replaced return value with null for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::allMatches → KILLED
|
return (matched, lineNumber) -> matched; |
|
95
|
|
} |
|
96
|
|
} |
| | Mutations |
| 65 |
|
1.1 Location : firstMatch Killed by : com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderBuilder.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderBuilder]/[method:builderIsFluentReturningItself()] replaced return value with null for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::firstMatch → KILLED
2.2 Location : lambda$firstMatch$0 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchFirstMatchUsesFirstRegisteredMappingOnly()] Substituted 0 with 1 → KILLED
3.3 Location : lambda$firstMatch$0 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchFirstMatchUsesFirstRegisteredMappingOnly()] replaced call to java/util/List::subList with receiver → KILLED
4.4 Location : lambda$firstMatch$0 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchFirstMatchUsesFirstRegisteredMappingOnly()] replaced return value with Collections.emptyList for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::lambda$firstMatch$0 → KILLED
5.5 Location : lambda$firstMatch$0 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchFirstMatchUsesFirstRegisteredMappingOnly()] Substituted 1 with 0 → KILLED
6.6 Location : lambda$firstMatch$0 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchFirstMatchUsesFirstRegisteredMappingOnly()] removed call to java/util/List::subList → KILLED
|
| 75 |
|
1.1 Location : throwOnAmbiguity Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchThrowOnAmbiguityThrowsWhenTwoPatternsMatch()] replaced return value with null for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::throwOnAmbiguity → KILLED
|
| 76 |
|
1.1 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchThrowOnAmbiguityThrowsWhenTwoPatternsMatch()] removed conditional - replaced comparison check with false → KILLED
2.2 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchThrowOnAmbiguityThrowsWhenTwoPatternsMatch()] negated conditional → KILLED
3.3 Location : lambda$throwOnAmbiguity$2 Killed by : none changed conditional boundary → SURVIVED
Covering tests
4.4 Location : lambda$throwOnAmbiguity$2 Killed by : none removed conditional - replaced comparison check with true → SURVIVED
Covering tests
5.5 Location : lambda$throwOnAmbiguity$2 Killed by : none Substituted 1 with 0 → SURVIVED
Covering tests
6.6 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchThrowOnAmbiguityThrowsWhenTwoPatternsMatch()] removed call to java/util/List::size → KILLED
|
| 77 |
|
1.1 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchThrowOnAmbiguityThrowsWhenTwoPatternsMatch()] removed call to java/util/List::stream → KILLED
|
| 78 |
|
1.1 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchThrowOnAmbiguityThrowsWhenTwoPatternsMatch()] removed call to java/util/stream/Stream::map → KILLED
2.2 Location : lambda$throwOnAmbiguity$1 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchThrowOnAmbiguityThrowsWhenTwoPatternsMatch()] removed call to com/ancientprogramming/fixedformat4j/io/read/RecordMapping::getRecordClass → KILLED
3.3 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchThrowOnAmbiguityThrowsWhenTwoPatternsMatch()] replaced call to java/util/stream/Stream::map with receiver → KILLED
4.4 Location : lambda$throwOnAmbiguity$1 Killed by : com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch]/[method:throwsOnAmbiguityWhenTwoPatternsMatch()] replaced return value with "" for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::lambda$throwOnAmbiguity$1 → KILLED
5.5 Location : lambda$throwOnAmbiguity$1 Killed by : com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch]/[method:throwsOnAmbiguityWhenTwoPatternsMatch()] removed call to java/lang/Class::getSimpleName → KILLED
|
| 79 |
|
1.1 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchThrowOnAmbiguityThrowsWhenTwoPatternsMatch()] removed call to java/util/stream/Collectors::joining → KILLED
2.2 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch]/[method:throwsOnAmbiguityWhenTwoPatternsMatch()] removed call to java/util/stream/Stream::collect → KILLED
|
| 80 |
|
1.1 Location : lambda$throwOnAmbiguity$2 Killed by : none Substituted 2 with 3 → SURVIVED
Covering tests
2.2 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch]/[method:throwsOnAmbiguityWhenTwoPatternsMatch()] Substituted 0 with 1 → KILLED
|
| 81 |
|
1.1 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch]/[method:throwsOnAmbiguityWhenTwoPatternsMatch()] replaced call to java/lang/String::format with argument → KILLED
2.2 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchThrowOnAmbiguityThrowsWhenTwoPatternsMatch()] Substituted 1 with 0 → KILLED
3.3 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchThrowOnAmbiguityThrowsWhenTwoPatternsMatch()] removed call to com/ancientprogramming/fixedformat4j/exception/FixedFormatException::<init> → KILLED
4.4 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch]/[method:throwsOnAmbiguityWhenTwoPatternsMatch()] removed call to java/lang/Long::valueOf → KILLED
5.5 Location : lambda$throwOnAmbiguity$2 Killed by : com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestFixedFormatReaderMultiMatch]/[method:throwsOnAmbiguityWhenTwoPatternsMatch()] removed call to java/lang/String::format → KILLED
|
| 83 |
|
1.1 Location : lambda$throwOnAmbiguity$2 Killed by : none replaced return value with Collections.emptyList for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::lambda$throwOnAmbiguity$2 → NO_COVERAGE
|
| 94 |
|
1.1 Location : lambda$allMatches$3 Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchAllMatchesEmitsOneRecordPerMatchingMapping()] replaced return value with Collections.emptyList for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::lambda$allMatches$3 → KILLED
2.2 Location : allMatches Killed by : com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.io.TestStrategiesAndHandlers]/[method:multiMatchAllMatchesEmitsOneRecordPerMatchingMapping()] replaced return value with null for com/ancientprogramming/fixedformat4j/io/read/MultiMatchStrategy::allMatches → KILLED
|