This is an automated email from the ASF dual-hosted git repository.
bchapuis pushed a commit to branch csv-datastore
in repository https://gitbox.apache.org/repos/asf/incubator-baremaps.git
The following commit(s) were added to refs/heads/csv-datastore by this push:
new 6ea1c0bdb Format the source code
6ea1c0bdb is described below
commit 6ea1c0bdb7b5c383d1de016ae1e002180344f261
Author: Bertil Chapuis <[email protected]>
AuthorDate: Wed Oct 30 21:11:17 2024 +0100
Format the source code
---
.../apache/baremaps/geocoder/GeonamesReader.java | 2 -
.../apache/baremaps/storage/csv/CsvDataStore.java | 139 ++++----
.../apache/baremaps/storage/csv/CsvDataTable.java | 358 +++++++++++----------
.../storage/csv/CsvDataTableGeonamesTest.java | 225 +++++++------
.../baremaps/storage/csv/CsvDataTableTest.java | 342 ++++++++++----------
5 files changed, 565 insertions(+), 501 deletions(-)
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/geocoder/GeonamesReader.java
b/baremaps-core/src/main/java/org/apache/baremaps/geocoder/GeonamesReader.java
index 53a18dc8f..b35c4c45f 100644
---
a/baremaps-core/src/main/java/org/apache/baremaps/geocoder/GeonamesReader.java
+++
b/baremaps-core/src/main/java/org/apache/baremaps/geocoder/GeonamesReader.java
@@ -22,8 +22,6 @@ package org.apache.baremaps.geocoder;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
-import com.fasterxml.jackson.dataformat.csv.CsvSchema.ColumnType;
-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/storage/csv/CsvDataStore.java
b/baremaps-core/src/main/java/org/apache/baremaps/storage/csv/CsvDataStore.java
index f79112427..93b0624a9 100644
---
a/baremaps-core/src/main/java/org/apache/baremaps/storage/csv/CsvDataStore.java
+++
b/baremaps-core/src/main/java/org/apache/baremaps/storage/csv/CsvDataStore.java
@@ -1,81 +1,98 @@
-package org.apache.baremaps.storage.csv;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-import org.apache.baremaps.data.storage.DataSchema;
-import org.apache.baremaps.data.storage.DataStore;
-import org.apache.baremaps.data.storage.DataStoreException;
-import org.apache.baremaps.data.storage.DataTable;
+package org.apache.baremaps.storage.csv;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
+import org.apache.baremaps.data.storage.DataSchema;
+import org.apache.baremaps.data.storage.DataStore;
+import org.apache.baremaps.data.storage.DataStoreException;
+import org.apache.baremaps.data.storage.DataTable;
/**
* A DataStore implementation that manages a single CSV file.
*/
public class CsvDataStore implements DataStore {
- private final String tableName;
- private final DataSchema schema;
- private final CsvDataTable dataTable;
+ private final String tableName;
+ private final DataSchema schema;
+ private final CsvDataTable dataTable;
- /**
- * Constructs a CsvDataStore with the specified table name, schema, and
CSV file.
- *
- * @param tableName the name of the table
- * @param schema the data schema defining the structure
- * @param csvFile the CSV file to read data from
- * @param hasHeader whether the CSV file includes a header row
- * @param separator the character used to separate columns in the CSV file
- * @throws IOException if an I/O error occurs
- */
- public CsvDataStore(String tableName, DataSchema schema, File csvFile,
boolean hasHeader, char separator) throws IOException {
- this.tableName = tableName;
- this.schema = schema;
- this.dataTable = new CsvDataTable(schema, csvFile, hasHeader,
separator);
- }
+ /**
+ * Constructs a CsvDataStore with the specified table name, schema, and CSV
file.
+ *
+ * @param tableName the name of the table
+ * @param schema the data schema defining the structure
+ * @param csvFile the CSV file to read data from
+ * @param hasHeader whether the CSV file includes a header row
+ * @param separator the character used to separate columns in the CSV file
+ * @throws IOException if an I/O error occurs
+ */
+ public CsvDataStore(String tableName, DataSchema schema, File csvFile,
boolean hasHeader,
+ char separator) throws IOException {
+ this.tableName = tableName;
+ this.schema = schema;
+ this.dataTable = new CsvDataTable(schema, csvFile, hasHeader, separator);
+ }
- /**
- * {@inheritDoc}
- */
- @Override
- public List<String> list() throws DataStoreException {
- return Collections.singletonList(tableName);
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<String> list() throws DataStoreException {
+ return Collections.singletonList(tableName);
+ }
- /**
- * {@inheritDoc}
- */
- @Override
- public DataTable get(String name) throws DataStoreException {
- if (this.tableName.equals(name)) {
- return dataTable;
- } else {
- throw new DataStoreException("Table '" + name + "' not found.");
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public DataTable get(String name) throws DataStoreException {
+ if (this.tableName.equals(name)) {
+ return dataTable;
+ } else {
+ throw new DataStoreException("Table '" + name + "' not found.");
}
+ }
- /**
- * {@inheritDoc}
- */
- @Override
- public void add(DataTable table) throws DataStoreException {
- throw new UnsupportedOperationException("Adding tables is not
supported in CsvDataStore.");
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void add(DataTable table) throws DataStoreException {
+ throw new UnsupportedOperationException("Adding tables is not supported in
CsvDataStore.");
+ }
- /**
- * {@inheritDoc}
- */
- @Override
- public void add(String name, DataTable table) throws DataStoreException {
- throw new UnsupportedOperationException("Adding tables is not
supported in CsvDataStore.");
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void add(String name, DataTable table) throws DataStoreException {
+ throw new UnsupportedOperationException("Adding tables is not supported in
CsvDataStore.");
+ }
- /**
- * {@inheritDoc}
- */
- @Override
- public void remove(String name) throws DataStoreException {
- throw new UnsupportedOperationException("Removing tables is not
supported in CsvDataStore.");
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void remove(String name) throws DataStoreException {
+ throw new UnsupportedOperationException("Removing tables is not supported
in CsvDataStore.");
+ }
}
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/storage/csv/CsvDataTable.java
b/baremaps-core/src/main/java/org/apache/baremaps/storage/csv/CsvDataTable.java
index f1ec2afcf..aa92e6ad0 100644
---
a/baremaps-core/src/main/java/org/apache/baremaps/storage/csv/CsvDataTable.java
+++
b/baremaps-core/src/main/java/org/apache/baremaps/storage/csv/CsvDataTable.java
@@ -1,199 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.apache.baremaps.storage.csv;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
-import org.apache.baremaps.data.storage.DataColumn;
-import org.apache.baremaps.data.storage.DataRow;
-import org.apache.baremaps.data.storage.DataSchema;
-import org.apache.baremaps.data.storage.DataTable;
-import org.locationtech.jts.io.WKTReader;
-
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
+import org.apache.baremaps.data.storage.DataColumn;
+import org.apache.baremaps.data.storage.DataRow;
+import org.apache.baremaps.data.storage.DataSchema;
+import org.apache.baremaps.data.storage.DataTable;
+import org.locationtech.jts.io.WKTReader;
/**
* A DataTable implementation that reads data from a CSV file using Jackson.
*/
public class CsvDataTable implements DataTable {
- private final DataSchema schema;
- private final File csvFile;
- private final CsvSchema csvSchema;
- private final long size;
-
- /**
- * Constructs a CsvDataTable with the specified schema, CSV file, header
presence, and separator.
- *
- * @param schema the data schema defining the structure
- * @param csvFile the CSV file to read data from
- * @param hasHeader whether the CSV file includes a header row
- * @param separator the character used to separate columns in the CSV file
- * @throws IOException if an I/O error occurs
- */
- public CsvDataTable(DataSchema schema, File csvFile, boolean hasHeader,
char separator) throws IOException {
- this.schema = schema;
- this.csvFile = csvFile;
- this.csvSchema = buildCsvSchema(schema, hasHeader, separator);
- this.size = calculateSize();
+ private final DataSchema schema;
+ private final File csvFile;
+ private final CsvSchema csvSchema;
+ private final long size;
+
+ /**
+ * Constructs a CsvDataTable with the specified schema, CSV file, header
presence, and separator.
+ *
+ * @param schema the data schema defining the structure
+ * @param csvFile the CSV file to read data from
+ * @param hasHeader whether the CSV file includes a header row
+ * @param separator the character used to separate columns in the CSV file
+ * @throws IOException if an I/O error occurs
+ */
+ public CsvDataTable(DataSchema schema, File csvFile, boolean hasHeader, char
separator)
+ throws IOException {
+ this.schema = schema;
+ this.csvFile = csvFile;
+ this.csvSchema = buildCsvSchema(schema, hasHeader, separator);
+ this.size = calculateSize();
+ }
+
+ /**
+ * Builds the CsvSchema for Jackson based on the provided DataSchema, header
presence, and
+ * separator.
+ *
+ * @param dataSchema the data schema
+ * @param hasHeader whether the CSV file includes a header row
+ * @param separator the character used to separate columns
+ * @return the CsvSchema for Jackson
+ */
+ private CsvSchema buildCsvSchema(DataSchema dataSchema, boolean hasHeader,
char separator) {
+ CsvSchema.Builder builder = CsvSchema.builder();
+ for (DataColumn column : dataSchema.columns()) {
+ builder.addColumn(column.name());
}
-
- /**
- * Builds the CsvSchema for Jackson based on the provided DataSchema,
header presence, and separator.
- *
- * @param dataSchema the data schema
- * @param hasHeader whether the CSV file includes a header row
- * @param separator the character used to separate columns
- * @return the CsvSchema for Jackson
- */
- private CsvSchema buildCsvSchema(DataSchema dataSchema, boolean hasHeader,
char separator) {
- CsvSchema.Builder builder = CsvSchema.builder();
- for (DataColumn column : dataSchema.columns()) {
- builder.addColumn(column.name());
+ CsvSchema schema =
builder.setUseHeader(hasHeader).setColumnSeparator(separator).build();
+ return schema;
+ }
+
+ /**
+ * Calculates the number of rows in the CSV file.
+ *
+ * @return the number of rows
+ * @throws IOException if an I/O error occurs
+ */
+ private long calculateSize() throws IOException {
+ try (var parser = new CsvMapper().readerFor(Map.class)
+ .with(csvSchema)
+ .createParser(csvFile)) {
+ long rowCount = 0;
+ while (parser.nextToken() != null) {
+ if (parser.currentToken() == JsonToken.START_OBJECT) {
+ rowCount++;
}
- CsvSchema schema =
builder.setUseHeader(hasHeader).setColumnSeparator(separator).build();
- return schema;
+ }
+ return rowCount;
}
+ }
+
+ @Override
+ public DataSchema schema() {
+ return schema;
+ }
+
+ @Override
+ public boolean add(DataRow row) {
+ throw new UnsupportedOperationException("Adding rows is not supported.");
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException("Clearing rows is not supported.");
+ }
+
+ @Override
+ public long size() {
+ return size;
+ }
+
+ @Override
+ public Iterator<DataRow> iterator() {
+ try {
+ CsvMapper csvMapper = new CsvMapper();
+ JsonParser parser = csvMapper.readerFor(Map.class)
+ .with(csvSchema)
+ .createParser(csvFile);
+
+ Iterator<Map<String, String>> csvIterator =
csvMapper.readerFor(Map.class)
+ .with(csvSchema)
+ .readValues(parser);
+
+ return new Iterator<>() {
+ @Override
+ public boolean hasNext() {
+ return csvIterator.hasNext();
+ }
- /**
- * Calculates the number of rows in the CSV file.
- *
- * @return the number of rows
- * @throws IOException if an I/O error occurs
- */
- private long calculateSize() throws IOException {
- try (var parser = new CsvMapper().readerFor(Map.class)
- .with(csvSchema)
- .createParser(csvFile)) {
- long rowCount = 0;
- while (parser.nextToken() != null) {
- if (parser.currentToken() == JsonToken.START_OBJECT) {
- rowCount++;
- }
+ @Override
+ public DataRow next() {
+ Map<String, String> csvRow = csvIterator.next();
+ DataRow dataRow = schema.createRow();
+
+ for (int i = 0; i < schema.columns().size(); i++) {
+ DataColumn column = schema.columns().get(i);
+ String columnName = column.name();
+ String value = csvRow.get(columnName);
+
+ if (value != null) {
+ Object parsedValue = parseValue(column, value);
+ dataRow.set(i, parsedValue);
+ } else {
+ dataRow.set(i, null);
}
- return rowCount;
+ }
+ return dataRow;
}
- }
+ };
- @Override
- public DataSchema schema() {
- return schema;
+ } catch (IOException e) {
+ throw new RuntimeException("Error reading CSV file", e);
}
-
- @Override
- public boolean add(DataRow row) {
- throw new UnsupportedOperationException("Adding rows is not
supported.");
- }
-
- @Override
- public void clear() {
- throw new UnsupportedOperationException("Clearing rows is not
supported.");
- }
-
- @Override
- public long size() {
- return size;
+ }
+
+ /**
+ * Parses the string value from the CSV according to the column type.
+ *
+ * @param column the data column
+ * @param value the string value from the CSV
+ * @return the parsed value
+ */
+ private Object parseValue(DataColumn column, String value) {
+ DataColumn.Type type = column.type();
+ try {
+ if (value == null || value.isEmpty()) {
+ return null;
+ }
+ switch (type) {
+ case STRING:
+ return value;
+ case INTEGER:
+ return Integer.parseInt(value);
+ case LONG:
+ return Long.parseLong(value);
+ case FLOAT:
+ return Float.parseFloat(value);
+ case DOUBLE:
+ return Double.parseDouble(value);
+ case BOOLEAN:
+ return Boolean.parseBoolean(value);
+ case GEOMETRY:
+ case POINT:
+ case LINESTRING:
+ case POLYGON:
+ case MULTIPOINT:
+ case MULTILINESTRING:
+ case MULTIPOLYGON:
+ case GEOMETRYCOLLECTION:
+ WKTReader reader = new WKTReader();
+ return reader.read(value);
+ default:
+ throw new IllegalArgumentException("Unsupported column type: " +
type);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Error parsing value for column " +
column.name(), e);
}
+ }
- @Override
- public Iterator<DataRow> iterator() {
- try {
- CsvMapper csvMapper = new CsvMapper();
- JsonParser parser = csvMapper.readerFor(Map.class)
- .with(csvSchema)
- .createParser(csvFile);
-
- Iterator<Map<String, String>> csvIterator =
csvMapper.readerFor(Map.class)
- .with(csvSchema)
- .readValues(parser);
-
- return new Iterator<>() {
- @Override
- public boolean hasNext() {
- return csvIterator.hasNext();
- }
-
- @Override
- public DataRow next() {
- Map<String, String> csvRow = csvIterator.next();
- DataRow dataRow = schema.createRow();
-
- for (int i = 0; i < schema.columns().size(); i++) {
- DataColumn column = schema.columns().get(i);
- String columnName = column.name();
- String value = csvRow.get(columnName);
-
- if (value != null) {
- Object parsedValue = parseValue(column, value);
- dataRow.set(i, parsedValue);
- } else {
- dataRow.set(i, null);
- }
- }
- return dataRow;
- }
- };
-
- } catch (IOException e) {
- throw new RuntimeException("Error reading CSV file", e);
- }
- }
+ @Override
+ public Spliterator<DataRow> spliterator() {
+ return Spliterators.spliteratorUnknownSize(iterator(),
Spliterator.ORDERED);
+ }
- /**
- * Parses the string value from the CSV according to the column type.
- *
- * @param column the data column
- * @param value the string value from the CSV
- * @return the parsed value
- */
- private Object parseValue(DataColumn column, String value) {
- DataColumn.Type type = column.type();
- try {
- if (value == null || value.isEmpty()) {
- return null;
- }
- switch (type) {
- case STRING:
- return value;
- case INTEGER:
- return Integer.parseInt(value);
- case LONG:
- return Long.parseLong(value);
- case FLOAT:
- return Float.parseFloat(value);
- case DOUBLE:
- return Double.parseDouble(value);
- case BOOLEAN:
- return Boolean.parseBoolean(value);
- case GEOMETRY:
- case POINT:
- case LINESTRING:
- case POLYGON:
- case MULTIPOINT:
- case MULTILINESTRING:
- case MULTIPOLYGON:
- case GEOMETRYCOLLECTION:
- WKTReader reader = new WKTReader();
- return reader.read(value);
- default:
- throw new IllegalArgumentException("Unsupported column
type: " + type);
- }
- } catch (Exception e) {
- throw new RuntimeException("Error parsing value for column " +
column.name(), e);
- }
- }
-
- @Override
- public Spliterator<DataRow> spliterator() {
- return Spliterators.spliteratorUnknownSize(iterator(),
Spliterator.ORDERED);
- }
-
- @Override
- public Stream<DataRow> stream() {
- return StreamSupport.stream(spliterator(), false);
- }
+ @Override
+ public Stream<DataRow> stream() {
+ return StreamSupport.stream(spliterator(), false);
+ }
}
diff --git
a/baremaps-core/src/test/java/org/apache/baremaps/storage/csv/CsvDataTableGeonamesTest.java
b/baremaps-core/src/test/java/org/apache/baremaps/storage/csv/CsvDataTableGeonamesTest.java
index 23499e976..5bdf79900 100644
---
a/baremaps-core/src/test/java/org/apache/baremaps/storage/csv/CsvDataTableGeonamesTest.java
+++
b/baremaps-core/src/test/java/org/apache/baremaps/storage/csv/CsvDataTableGeonamesTest.java
@@ -1,120 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.apache.baremaps.storage.csv;
-import org.apache.baremaps.data.storage.*;
-import org.junit.jupiter.api.*;
-import org.locationtech.jts.geom.Point;
+import static org.apache.baremaps.testing.TestFiles.GEONAMES_CSV;
+import static org.junit.jupiter.api.Assertions.*;
import java.io.IOException;
import java.util.List;
-
-import static org.apache.baremaps.testing.TestFiles.GEONAMES_CSV;
-import static org.junit.jupiter.api.Assertions.*;
+import org.apache.baremaps.data.storage.*;
+import org.junit.jupiter.api.*;
+import org.locationtech.jts.geom.Point;
class CsvDataTableGeonamesTest {
- @Test
- void testGeonamesCsvDataTable() throws IOException {
- List<DataColumn> columns = List.of(
- new DataColumnFixed("id", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
- new DataColumnFixed("name", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
- new DataColumnFixed("asciiname",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING),
- new DataColumnFixed("alternatenames",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING),
- new DataColumnFixed("latitude",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.DOUBLE),
- new DataColumnFixed("longitude",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.DOUBLE),
- new DataColumnFixed("feature_class",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING),
- new DataColumnFixed("feature_code",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING),
- new DataColumnFixed("country_code",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING),
- new DataColumnFixed("cc2", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
- new DataColumnFixed("admin1_code",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING),
- new DataColumnFixed("admin2_code",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING),
- new DataColumnFixed("admin3_code",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING),
- new DataColumnFixed("admin4_code",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING),
- new DataColumnFixed("population",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.LONG),
- new DataColumnFixed("elevation",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.INTEGER),
- new DataColumnFixed("dem", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.INTEGER),
- new DataColumnFixed("timezone",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING),
- new DataColumnFixed("modification_date",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING)
- );
- DataSchema schema = new DataSchemaImpl("geonames", columns);
+ @Test
+ void testGeonamesCsvDataTable() throws IOException {
+ List<DataColumn> columns = List.of(
+ new DataColumnFixed("id", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
+ new DataColumnFixed("name", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
+ new DataColumnFixed("asciiname", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
+ new DataColumnFixed("alternatenames", DataColumn.Cardinality.OPTIONAL,
+ DataColumn.Type.STRING),
+ new DataColumnFixed("latitude", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.DOUBLE),
+ new DataColumnFixed("longitude", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.DOUBLE),
+ new DataColumnFixed("feature_class", DataColumn.Cardinality.OPTIONAL,
+ DataColumn.Type.STRING),
+ new DataColumnFixed("feature_code", DataColumn.Cardinality.OPTIONAL,
+ DataColumn.Type.STRING),
+ new DataColumnFixed("country_code", DataColumn.Cardinality.OPTIONAL,
+ DataColumn.Type.STRING),
+ new DataColumnFixed("cc2", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
+ new DataColumnFixed("admin1_code", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
+ new DataColumnFixed("admin2_code", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
+ new DataColumnFixed("admin3_code", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
+ new DataColumnFixed("admin4_code", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
+ new DataColumnFixed("population", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.LONG),
+ new DataColumnFixed("elevation", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.INTEGER),
+ new DataColumnFixed("dem", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.INTEGER),
+ new DataColumnFixed("timezone", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
+ new DataColumnFixed("modification_date",
DataColumn.Cardinality.OPTIONAL,
+ DataColumn.Type.STRING));
+ DataSchema schema = new DataSchemaImpl("geonames", columns);
- boolean hasHeader = false;
- char separator = '\t';
- DataTable dataTable = new CsvDataTable(schema, GEONAMES_CSV.toFile(),
hasHeader, separator);
+ boolean hasHeader = false;
+ char separator = '\t';
+ DataTable dataTable = new CsvDataTable(schema, GEONAMES_CSV.toFile(),
hasHeader, separator);
- assertEquals(5, dataTable.size(), "DataTable should have 5 rows.");
+ assertEquals(5, dataTable.size(), "DataTable should have 5 rows.");
- int rowCount = 0;
- for (DataRow row : dataTable) {
- rowCount++;
+ int rowCount = 0;
+ for (DataRow row : dataTable) {
+ rowCount++;
- // Extract values
- Integer id = (Integer) row.get("id");
- String name = (String) row.get("name");
- String asciiname = (String) row.get("asciiname");
- String alternatenames = (String) row.get("alternatenames");
- Double latitude = (Double) row.get("latitude");
- Double longitude = (Double) row.get("longitude");
- String featureClass = (String) row.get("feature_class");
- String featureCode = (String) row.get("feature_code");
- String countryCode = (String) row.get("country_code");
- String cc2 = (String) row.get("cc2");
- String admin1Code = (String) row.get("admin1_code");
- String admin2Code = (String) row.get("admin2_code");
- String admin3Code = (String) row.get("admin3_code");
- String admin4Code = (String) row.get("admin4_code");
- Long population = (Long) row.get("population");
- Integer elevation = (Integer) row.get("elevation");
- Integer dem = (Integer) row.get("dem");
- String timezone = (String) row.get("timezone");
- String modificationDate = (String) row.get("modification_date");
+ // Extract values
+ Integer id = (Integer) row.get("id");
+ String name = (String) row.get("name");
+ String asciiname = (String) row.get("asciiname");
+ String alternatenames = (String) row.get("alternatenames");
+ Double latitude = (Double) row.get("latitude");
+ Double longitude = (Double) row.get("longitude");
+ String featureClass = (String) row.get("feature_class");
+ String featureCode = (String) row.get("feature_code");
+ String countryCode = (String) row.get("country_code");
+ String cc2 = (String) row.get("cc2");
+ String admin1Code = (String) row.get("admin1_code");
+ String admin2Code = (String) row.get("admin2_code");
+ String admin3Code = (String) row.get("admin3_code");
+ String admin4Code = (String) row.get("admin4_code");
+ Long population = (Long) row.get("population");
+ Integer elevation = (Integer) row.get("elevation");
+ Integer dem = (Integer) row.get("dem");
+ String timezone = (String) row.get("timezone");
+ String modificationDate = (String) row.get("modification_date");
- // Perform assertions for each row
- assertNotNull(id, "ID should not be null.");
- assertNotNull(name, "Name should not be null.");
- assertNotNull(latitude, "Latitude should not be null.");
- assertNotNull(longitude, "Longitude should not be null.");
+ // Perform assertions for each row
+ assertNotNull(id, "ID should not be null.");
+ assertNotNull(name, "Name should not be null.");
+ assertNotNull(latitude, "Latitude should not be null.");
+ assertNotNull(longitude, "Longitude should not be null.");
- switch (id) {
- case 1:
- assertEquals("HEIG", name);
- assertEquals(1.111, latitude);
- assertEquals(1.111, longitude);
- break;
- case 2:
- assertEquals("Yverdon-les-bains", name);
- assertEquals(2.222, latitude);
- assertEquals(2.222, longitude);
- break;
- case 3:
- assertEquals("Route de Cheseaux 1", name);
- assertEquals(3.333, latitude);
- assertEquals(3.333, longitude);
- break;
- case 4:
- assertEquals("Switzerland", name);
- assertEquals(4.444, latitude);
- assertEquals(4.444, longitude);
- break;
- case 5:
- assertEquals("Switzerland", name);
- assertEquals(47.00016, latitude);
- assertEquals(8.01427, longitude);
- break;
- default:
- fail("Unexpected ID: " + id);
- }
+ switch (id) {
+ case 1:
+ assertEquals("HEIG", name);
+ assertEquals(1.111, latitude);
+ assertEquals(1.111, longitude);
+ break;
+ case 2:
+ assertEquals("Yverdon-les-bains", name);
+ assertEquals(2.222, latitude);
+ assertEquals(2.222, longitude);
+ break;
+ case 3:
+ assertEquals("Route de Cheseaux 1", name);
+ assertEquals(3.333, latitude);
+ assertEquals(3.333, longitude);
+ break;
+ case 4:
+ assertEquals("Switzerland", name);
+ assertEquals(4.444, latitude);
+ assertEquals(4.444, longitude);
+ break;
+ case 5:
+ assertEquals("Switzerland", name);
+ assertEquals(47.00016, latitude);
+ assertEquals(8.01427, longitude);
+ break;
+ default:
+ fail("Unexpected ID: " + id);
+ }
- Point point = createPoint(longitude, latitude);
- assertNotNull(point, "Point geometry should not be null.");
- }
- assertEquals(5, rowCount, "Row count should be 5.");
+ Point point = createPoint(longitude, latitude);
+ assertNotNull(point, "Point geometry should not be null.");
}
+ assertEquals(5, rowCount, "Row count should be 5.");
+ }
- private Point createPoint(Double longitude, Double latitude) {
- if (longitude != null && latitude != null) {
- return new
org.locationtech.jts.geom.GeometryFactory().createPoint(new
org.locationtech.jts.geom.Coordinate(longitude, latitude));
- } else {
- return null;
- }
+ private Point createPoint(Double longitude, Double latitude) {
+ if (longitude != null && latitude != null) {
+ return new org.locationtech.jts.geom.GeometryFactory()
+ .createPoint(new org.locationtech.jts.geom.Coordinate(longitude,
latitude));
+ } else {
+ return null;
}
-}
\ No newline at end of file
+ }
+}
diff --git
a/baremaps-core/src/test/java/org/apache/baremaps/storage/csv/CsvDataTableTest.java
b/baremaps-core/src/test/java/org/apache/baremaps/storage/csv/CsvDataTableTest.java
index 09747d9ea..a98c2957a 100644
---
a/baremaps-core/src/test/java/org/apache/baremaps/storage/csv/CsvDataTableTest.java
+++
b/baremaps-core/src/test/java/org/apache/baremaps/storage/csv/CsvDataTableTest.java
@@ -1,182 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.apache.baremaps.storage.csv;
-import org.apache.baremaps.data.storage.*;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.locationtech.jts.geom.Geometry;
+import static org.junit.jupiter.api.Assertions.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
+import org.apache.baremaps.data.storage.*;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.locationtech.jts.geom.Geometry;
class CsvDataTableTest {
- private File tempCsvFile;
-
- @BeforeEach
- void setUp() throws IOException {
- tempCsvFile = File.createTempFile("test", ".csv");
- tempCsvFile.deleteOnExit();
- }
-
- @AfterEach
- void tearDown() {
- if (tempCsvFile.exists()) {
- tempCsvFile.delete();
- }
- }
-
- @Test
- void testCsvWithHeaderAndCommaSeparator() throws IOException {
- String csvContent = """
- id,name,geom
- 1,PointA,"POINT(1 1)"
- 2,PointB,"POINT(2 2)"
- """;
- Files.writeString(tempCsvFile.toPath(), csvContent);
- List<DataColumn> columns = List.of(
- new DataColumnFixed("id", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
- new DataColumnFixed("name", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
- new DataColumnFixed("geom", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.GEOMETRY)
- );
- DataSchema schema = new DataSchemaImpl("test_table", columns);
- DataTable dataTable = new CsvDataTable(schema, tempCsvFile, true, ',');
- assertEquals(2, dataTable.size());
- int rowCount = 0;
- for (DataRow row : dataTable) {
- rowCount++;
- Integer id = (Integer) row.get("id");
- String name = (String) row.get("name");
- Geometry geometry = (Geometry) row.get("geom");
- assertNotNull(id);
- assertNotNull(name);
- assertNotNull(geometry);
- assertEquals("Point" + (rowCount == 1 ? "A" : "B"), name);
- assertEquals("POINT (" + rowCount + " " + rowCount + ")",
geometry.toText());
- }
- assertEquals(2, rowCount);
- }
+ private File tempCsvFile;
- @Test
- void testCsvWithoutHeaderAndSemicolonSeparator() throws IOException {
- String csvContent = """
- 1;PointA;"POINT(1 1)"
- 2;PointB;"POINT(2 2)"
- """;
- Files.writeString(tempCsvFile.toPath(), csvContent);
- List<DataColumn> columns = List.of(
- new DataColumnFixed("column1",
DataColumn.Cardinality.REQUIRED, DataColumn.Type.INTEGER),
- new DataColumnFixed("column2",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.STRING),
- new DataColumnFixed("column3",
DataColumn.Cardinality.OPTIONAL, DataColumn.Type.GEOMETRY)
- );
- DataSchema schema = new DataSchemaImpl("test_table", columns);
- DataTable dataTable = new CsvDataTable(schema, tempCsvFile, false,
';');
- assertEquals(2, dataTable.size());
- int rowCount = 0;
- for (DataRow row : dataTable) {
- rowCount++;
- Integer id = (Integer) row.get("column1");
- String name = (String) row.get("column2");
- Geometry geometry = (Geometry) row.get("column3");
-
- // Verify data
- assertNotNull(id);
- assertNotNull(name);
- assertNotNull(geometry);
-
- assertEquals("Point" + (rowCount == 1 ? "A" : "B"), name);
- assertEquals("POINT (" + rowCount + " " + rowCount + ")",
geometry.toText());
- }
- assertEquals(2, rowCount);
- }
+ @BeforeEach
+ void setUp() throws IOException {
+ tempCsvFile = File.createTempFile("test", ".csv");
+ tempCsvFile.deleteOnExit();
+ }
- @Test
- void testCsvWithDifferentDataTypes() throws IOException {
- String csvContent = """
- int_col,double_col,bool_col,string_col
- 1,1.1,true,Hello
- 2,2.2,false,World
- """;
- Files.writeString(tempCsvFile.toPath(), csvContent);
- List<DataColumn> columns = List.of(
- new DataColumnFixed("int_col",
DataColumn.Cardinality.REQUIRED, DataColumn.Type.INTEGER),
- new DataColumnFixed("double_col",
DataColumn.Cardinality.REQUIRED, DataColumn.Type.DOUBLE),
- new DataColumnFixed("bool_col",
DataColumn.Cardinality.REQUIRED, DataColumn.Type.BOOLEAN),
- new DataColumnFixed("string_col",
DataColumn.Cardinality.REQUIRED, DataColumn.Type.STRING)
- );
- DataSchema schema = new DataSchemaImpl("test_table", columns);
- DataTable dataTable = new CsvDataTable(schema, tempCsvFile, true, ',');
- assertEquals(2, dataTable.size());
- int rowCount = 0;
- for (DataRow row : dataTable) {
- rowCount++;
- Integer intCol = (Integer) row.get("int_col");
- Double doubleCol = (Double) row.get("double_col");
- Boolean boolCol = (Boolean) row.get("bool_col");
- String stringCol = (String) row.get("string_col");
-
- // Verify data
- assertEquals(rowCount, intCol);
- assertEquals(rowCount * 1.1, doubleCol);
- assertEquals(rowCount == 1, boolCol);
- assertEquals(rowCount == 1 ? "Hello" : "World", stringCol);
- }
- assertEquals(2, rowCount);
+ @AfterEach
+ void tearDown() {
+ if (tempCsvFile.exists()) {
+ tempCsvFile.delete();
}
-
- @Test
- void testCsvWithInvalidData() throws IOException {
- String csvContent = """
- id,name
- abc,TestName
- """;
- Files.writeString(tempCsvFile.toPath(), csvContent);
- List<DataColumn> columns = List.of(
- new DataColumnFixed("id", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
- new DataColumnFixed("name", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING)
- );
- DataSchema schema = new DataSchemaImpl("test_table", columns);
- DataTable dataTable = new CsvDataTable(schema, tempCsvFile, true, ',');
- assertThrows(RuntimeException.class, () -> {
- for (DataRow row : dataTable) {
- // This line should throw an exception because abc is not a
valid integer
- }
- });
+ }
+
+ @Test
+ void testCsvWithHeaderAndCommaSeparator() throws IOException {
+ String csvContent = """
+ id,name,geom
+ 1,PointA,"POINT(1 1)"
+ 2,PointB,"POINT(2 2)"
+ """;
+ Files.writeString(tempCsvFile.toPath(), csvContent);
+ List<DataColumn> columns = List.of(
+ new DataColumnFixed("id", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
+ new DataColumnFixed("name", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
+ new DataColumnFixed("geom", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.GEOMETRY));
+ DataSchema schema = new DataSchemaImpl("test_table", columns);
+ DataTable dataTable = new CsvDataTable(schema, tempCsvFile, true, ',');
+ assertEquals(2, dataTable.size());
+ int rowCount = 0;
+ for (DataRow row : dataTable) {
+ rowCount++;
+ Integer id = (Integer) row.get("id");
+ String name = (String) row.get("name");
+ Geometry geometry = (Geometry) row.get("geom");
+ assertNotNull(id);
+ assertNotNull(name);
+ assertNotNull(geometry);
+ assertEquals("Point" + (rowCount == 1 ? "A" : "B"), name);
+ assertEquals("POINT (" + rowCount + " " + rowCount + ")",
geometry.toText());
}
-
- @Test
- void testAddAndClearUnsupportedOperations() throws IOException {
- String csvContent = "";
- Files.writeString(tempCsvFile.toPath(), csvContent);
- List<DataColumn> columns = List.of(
- new DataColumnFixed("id", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
- new DataColumnFixed("name", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING)
- );
- DataSchema schema = new DataSchemaImpl("test_table", columns);
- DataTable dataTable = new CsvDataTable(schema, tempCsvFile, true, ',');
- assertThrows(UnsupportedOperationException.class, () ->
dataTable.add(null));
- assertThrows(UnsupportedOperationException.class, dataTable::clear);
+ assertEquals(2, rowCount);
+ }
+
+ @Test
+ void testCsvWithoutHeaderAndSemicolonSeparator() throws IOException {
+ String csvContent = """
+ 1;PointA;"POINT(1 1)"
+ 2;PointB;"POINT(2 2)"
+ """;
+ Files.writeString(tempCsvFile.toPath(), csvContent);
+ List<DataColumn> columns = List.of(
+ new DataColumnFixed("column1", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
+ new DataColumnFixed("column2", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING),
+ new DataColumnFixed("column3", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.GEOMETRY));
+ DataSchema schema = new DataSchemaImpl("test_table", columns);
+ DataTable dataTable = new CsvDataTable(schema, tempCsvFile, false, ';');
+ assertEquals(2, dataTable.size());
+ int rowCount = 0;
+ for (DataRow row : dataTable) {
+ rowCount++;
+ Integer id = (Integer) row.get("column1");
+ String name = (String) row.get("column2");
+ Geometry geometry = (Geometry) row.get("column3");
+
+ // Verify data
+ assertNotNull(id);
+ assertNotNull(name);
+ assertNotNull(geometry);
+
+ assertEquals("Point" + (rowCount == 1 ? "A" : "B"), name);
+ assertEquals("POINT (" + rowCount + " " + rowCount + ")",
geometry.toText());
}
-
- @Test
- void testSizeCalculation() throws IOException {
- String csvContent = """
- id,name
- 1,Name1
- 2,Name2
- 3,Name3
- """;
- Files.writeString(tempCsvFile.toPath(), csvContent);
- List<DataColumn> columns = List.of(
- new DataColumnFixed("id", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
- new DataColumnFixed("name", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING)
- );
- DataSchema schema = new DataSchemaImpl("test_table", columns);
- DataTable dataTable = new CsvDataTable(schema, tempCsvFile, true, ',');
- assertEquals(3, dataTable.size());
+ assertEquals(2, rowCount);
+ }
+
+ @Test
+ void testCsvWithDifferentDataTypes() throws IOException {
+ String csvContent = """
+ int_col,double_col,bool_col,string_col
+ 1,1.1,true,Hello
+ 2,2.2,false,World
+ """;
+ Files.writeString(tempCsvFile.toPath(), csvContent);
+ List<DataColumn> columns = List.of(
+ new DataColumnFixed("int_col", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
+ new DataColumnFixed("double_col", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.DOUBLE),
+ new DataColumnFixed("bool_col", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.BOOLEAN),
+ new DataColumnFixed("string_col", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.STRING));
+ DataSchema schema = new DataSchemaImpl("test_table", columns);
+ DataTable dataTable = new CsvDataTable(schema, tempCsvFile, true, ',');
+ assertEquals(2, dataTable.size());
+ int rowCount = 0;
+ for (DataRow row : dataTable) {
+ rowCount++;
+ Integer intCol = (Integer) row.get("int_col");
+ Double doubleCol = (Double) row.get("double_col");
+ Boolean boolCol = (Boolean) row.get("bool_col");
+ String stringCol = (String) row.get("string_col");
+
+ // Verify data
+ assertEquals(rowCount, intCol);
+ assertEquals(rowCount * 1.1, doubleCol);
+ assertEquals(rowCount == 1, boolCol);
+ assertEquals(rowCount == 1 ? "Hello" : "World", stringCol);
}
-}
\ No newline at end of file
+ assertEquals(2, rowCount);
+ }
+
+ @Test
+ void testCsvWithInvalidData() throws IOException {
+ String csvContent = """
+ id,name
+ abc,TestName
+ """;
+ Files.writeString(tempCsvFile.toPath(), csvContent);
+ List<DataColumn> columns = List.of(
+ new DataColumnFixed("id", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
+ new DataColumnFixed("name", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING));
+ DataSchema schema = new DataSchemaImpl("test_table", columns);
+ DataTable dataTable = new CsvDataTable(schema, tempCsvFile, true, ',');
+ assertThrows(RuntimeException.class, () -> {
+ for (DataRow row : dataTable) {
+ // This line should throw an exception because abc is not a valid
integer
+ }
+ });
+ }
+
+ @Test
+ void testAddAndClearUnsupportedOperations() throws IOException {
+ String csvContent = "";
+ Files.writeString(tempCsvFile.toPath(), csvContent);
+ List<DataColumn> columns = List.of(
+ new DataColumnFixed("id", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
+ new DataColumnFixed("name", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING));
+ DataSchema schema = new DataSchemaImpl("test_table", columns);
+ DataTable dataTable = new CsvDataTable(schema, tempCsvFile, true, ',');
+ assertThrows(UnsupportedOperationException.class, () ->
dataTable.add(null));
+ assertThrows(UnsupportedOperationException.class, dataTable::clear);
+ }
+
+ @Test
+ void testSizeCalculation() throws IOException {
+ String csvContent = """
+ id,name
+ 1,Name1
+ 2,Name2
+ 3,Name3
+ """;
+ Files.writeString(tempCsvFile.toPath(), csvContent);
+ List<DataColumn> columns = List.of(
+ new DataColumnFixed("id", DataColumn.Cardinality.REQUIRED,
DataColumn.Type.INTEGER),
+ new DataColumnFixed("name", DataColumn.Cardinality.OPTIONAL,
DataColumn.Type.STRING));
+ DataSchema schema = new DataSchemaImpl("test_table", columns);
+ DataTable dataTable = new CsvDataTable(schema, tempCsvFile, true, ',');
+ assertEquals(3, dataTable.size());
+ }
+}