Skip to content

Commit 68f17d8

Browse files
committed
handle null name in CSVRecord accessors under ignoreHeaderCase
the case-insensitive header map used by ignoreHeaderCase rejects null keys, so guard the name in isMapped and get to return false / throw IllegalArgumentException like the default case-sensitive path.
1 parent 4b9e7de commit 68f17d8

2 files changed

Lines changed: 20 additions & 2 deletions

File tree

src/main/java/org/apache/commons/csv/CSVRecord.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public String get(final String name) {
127127
if (headerMap == null) {
128128
throw new IllegalStateException("No header mapping was specified, the record values can't be accessed by name");
129129
}
130-
final Integer index = headerMap.get(name);
130+
final Integer index = name == null ? null : headerMap.get(name);
131131
if (index == null) {
132132
throw new IllegalArgumentException(String.format("Mapping for %s not found, expected one of %s", name, headerMap.keySet()));
133133
}
@@ -243,7 +243,7 @@ public boolean isConsistent() {
243243
*/
244244
public boolean isMapped(final String name) {
245245
final Map<String, Integer> headerMap = getHeaderMapRaw();
246-
return headerMap != null && headerMap.containsKey(name);
246+
return name != null && headerMap != null && headerMap.containsKey(name);
247247
}
248248

249249
/**

src/test/java/org/apache/commons/csv/CSVRecordTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
import org.apache.commons.lang3.StringUtils;
4545
import org.junit.jupiter.api.BeforeEach;
4646
import org.junit.jupiter.api.Test;
47+
import org.junit.jupiter.params.ParameterizedTest;
48+
import org.junit.jupiter.params.provider.ValueSource;
4749

4850
class CSVRecordTest {
4951

@@ -228,6 +230,22 @@ void testIsSetString() {
228230
assertFalse(recordWithHeader.isSet("DOES NOT EXIST"));
229231
}
230232

233+
@ParameterizedTest
234+
@ValueSource(booleans = { false, true })
235+
void testNullNameAccessorsMatchAcrossIgnoreHeaderCase(final boolean ignoreHeaderCase) throws IOException {
236+
final CSVFormat format = CSVFormat.DEFAULT.builder().setHeader().setSkipHeaderRecord(true).setIgnoreHeaderCase(ignoreHeaderCase).get();
237+
try (CSVParser parser = CSVParser.parse("A,B\n1,2", format)) {
238+
final CSVRecord rec = parser.iterator().next();
239+
// A null name is never a mapped header, so the boolean guards return false rather than throwing,
240+
// regardless of ignoreHeaderCase (the case-insensitive header map rejects null keys).
241+
assertFalse(rec.isMapped(null));
242+
assertFalse(rec.isSet((String) null));
243+
// A null name (also reached from get((Enum) null)) reports a missing mapping, not an NPE.
244+
assertThrows(IllegalArgumentException.class, () -> rec.get((String) null));
245+
assertThrows(IllegalArgumentException.class, () -> rec.get((Enum<?>) null));
246+
}
247+
}
248+
231249
@Test
232250
void testIterator() {
233251
int i = 0;

0 commit comments

Comments
 (0)