From 70ee7d9a305d4f2ded7769d6727f066e8bc076b9 Mon Sep 17 00:00:00 2001 From: Thomas Calmant Date: Mon, 9 Oct 2023 12:59:35 +0200 Subject: [PATCH] Small fix to ensure header-less CSV paths are used as integers --- .../device/factory/parser/csv/CsvParser.java | 2 +- .../device/factory/parser/csv/CsvRecord.java | 13 ++++++++--- .../device/factory/impl/CSVParserTest.java | 23 +++++++++++++++++++ .../csv/csv-no-header-vars-mapping.json | 21 +++++++++++++++++ .../test/resources/csv/csv-no-header-vars.csv | 2 ++ 5 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 southbound/device-factory/parser-csv/src/test/resources/csv/csv-no-header-vars-mapping.json create mode 100644 southbound/device-factory/parser-csv/src/test/resources/csv/csv-no-header-vars.csv diff --git a/southbound/device-factory/parser-csv/src/main/java/org/eclipse/sensinact/gateway/southbound/device/factory/parser/csv/CsvParser.java b/southbound/device-factory/parser-csv/src/main/java/org/eclipse/sensinact/gateway/southbound/device/factory/parser/csv/CsvParser.java index ac729fff3..6c58f6a17 100644 --- a/southbound/device-factory/parser-csv/src/main/java/org/eclipse/sensinact/gateway/southbound/device/factory/parser/csv/CsvParser.java +++ b/southbound/device-factory/parser-csv/src/main/java/org/eclipse/sensinact/gateway/southbound/device/factory/parser/csv/CsvParser.java @@ -77,7 +77,7 @@ public List parseRecords(byte[] rawInput, Map records = new ArrayList<>(); try (CSVParser parser = format.build().parse(new InputStreamReader(input, charset))) { for (CSVRecord record : parser) { - records.add(new CsvRecord(record)); + records.add(new CsvRecord(record, withHeader != null && !withHeader)); } } catch (IllegalStateException | IOException e) { throw new ParserException("Error reading CSV content", e); diff --git a/southbound/device-factory/parser-csv/src/main/java/org/eclipse/sensinact/gateway/southbound/device/factory/parser/csv/CsvRecord.java b/southbound/device-factory/parser-csv/src/main/java/org/eclipse/sensinact/gateway/southbound/device/factory/parser/csv/CsvRecord.java index 527065842..58499db75 100644 --- a/southbound/device-factory/parser-csv/src/main/java/org/eclipse/sensinact/gateway/southbound/device/factory/parser/csv/CsvRecord.java +++ b/southbound/device-factory/parser-csv/src/main/java/org/eclipse/sensinact/gateway/southbound/device/factory/parser/csv/CsvRecord.java @@ -31,13 +31,20 @@ public class CsvRecord implements IDeviceMappingRecord { */ private final CSVRecord record; + /** + * Flag to indicate the paths must all be a column index + */ + private final boolean columnIndexOnly; + /** * Sets up the CSV record * - * @param record Current parsed CSV record + * @param record Current parsed CSV record + * @param columnIndexOnly If true, all paths are considered column indices */ - public CsvRecord(final CSVRecord record) { + public CsvRecord(final CSVRecord record, final boolean columnIndexOnly) { this.record = record; + this.columnIndexOnly = columnIndexOnly; } /** @@ -48,7 +55,7 @@ public CsvRecord(final CSVRecord record) { */ private String getValue(final RecordPath path) { try { - if (path.isInt()) { + if (path.isInt() || columnIndexOnly) { return this.record.get(path.asInt()); } else { return this.record.get(path.asString()); diff --git a/southbound/device-factory/parser-csv/src/test/java/org/eclipse/sensinact/gateway/southbound/device/factory/impl/CSVParserTest.java b/southbound/device-factory/parser-csv/src/test/java/org/eclipse/sensinact/gateway/southbound/device/factory/impl/CSVParserTest.java index 4be58023b..491c04a80 100644 --- a/southbound/device-factory/parser-csv/src/test/java/org/eclipse/sensinact/gateway/southbound/device/factory/impl/CSVParserTest.java +++ b/southbound/device-factory/parser-csv/src/test/java/org/eclipse/sensinact/gateway/southbound/device/factory/impl/CSVParserTest.java @@ -359,4 +359,27 @@ void testIsolatedValueTyped() throws Exception { // CSV loads strings by default assertEquals(37.5f, getResourceValue(provider, "data", "value", Float.class)); } + + /** + * Mapping based on variables in multiple places + */ + @Test + void testVariables() throws Exception { + // Excepted resource + final String provider = "provider-vars-" + String.valueOf(new Random().nextInt()); + final String service = "svc-vars-" + String.valueOf(new Random().nextInt()); + final String resource = "rc-vars-" + String.valueOf(new Random().nextInt()); + + // Read the configuration + DeviceMappingConfigurationDTO config = readConfiguration("csv/csv-no-header-vars-mapping.json"); + + // Read the file + byte[] fileContent = readFile("csv/csv-no-header-vars.csv"); + + // Apply mapping + deviceMapper.handle(config, Map.of("provider", provider, "svc", service, "rc", resource), fileContent); + + assertEquals("3.4", getResourceValue(provider, service, "a", String.class)); + assertEquals("42", getResourceValue(provider, service, "b", String.class)); + } } diff --git a/southbound/device-factory/parser-csv/src/test/resources/csv/csv-no-header-vars-mapping.json b/southbound/device-factory/parser-csv/src/test/resources/csv/csv-no-header-vars-mapping.json new file mode 100644 index 000000000..3ab5a7072 --- /dev/null +++ b/southbound/device-factory/parser-csv/src/test/resources/csv/csv-no-header-vars-mapping.json @@ -0,0 +1,21 @@ +{ + "parser": "csv", + "parser.options": { + "header": false + }, + "mapping": { + "@provider": { + "literal": "${context.provider}" + }, + "$svcName": "${context.svc}", + "@datetime": 0, + "$rcName": 1, + "$rcValue": { + "path": 2, + "type": "int" + }, + "${svcName}/${rcName}": { + "path": "${rcValue}" + } + } +} diff --git a/southbound/device-factory/parser-csv/src/test/resources/csv/csv-no-header-vars.csv b/southbound/device-factory/parser-csv/src/test/resources/csv/csv-no-header-vars.csv new file mode 100644 index 000000000..8088815bf --- /dev/null +++ b/southbound/device-factory/parser-csv/src/test/resources/csv/csv-no-header-vars.csv @@ -0,0 +1,2 @@ +2023-10-09T08:14:00.0+02:00,a,4,1.2,3.4,21 +2023-10-09T08:17:00.0+02:00,b,5,5.6,7.8,42