This is an automated email from the ASF dual-hosted git repository.

bchapuis pushed a commit to branch collection
in repository https://gitbox.apache.org/repos/asf/incubator-baremaps.git

commit 0a45b4161b5791d5f2854d590744431be93b53f1
Author: Bertil Chapuis <[email protected]>
AuthorDate: Tue May 7 14:49:01 2024 +0200

    Improve the collection api and the javadoc
---
 .../database/collection/AppendOnlyLog.java         |  67 +++----
 .../database/collection/DataCollection.java        |  57 +++---
 .../collection/DataCollectionException.java        |   1 +
 .../database/collection/DataCollectionMapper.java  |   6 +-
 .../database/collection/DataConversions.java       | 193 ++++++++++++++++++++-
 .../baremaps/database/collection/DataList.java     |  12 +-
 .../baremaps/database/collection/DataMap.java      | 103 ++++++-----
 .../database/collection/FixedSizeDataList.java     |  27 +--
 .../database/collection/IndexedDataList.java       |  32 ++--
 .../database/collection/IndexedDataMap.java        |  60 ++-----
 .../database/collection/MemoryAlignedDataList.java |   9 +-
 .../database/collection/MemoryAlignedDataMap.java  |  10 +-
 .../database/collection/MonotonicDataMap.java      |  24 +--
 .../collection/MonotonicFixedSizeDataMap.java      |  14 +-
 .../collection/MonotonicPairedDataMap.java         |  18 +-
 .../apache/baremaps/database/memory/Memory.java    |   5 +
 .../baremaps/database/memory/MemoryException.java  |   1 +
 .../apache/baremaps/geocoder/GeonamesReader.java   |   1 -
 .../storage/postgres/PostgresDataTable.java        |   2 +-
 .../baremaps/database/AppendOnlyLogTest.java       |   4 +-
 .../org/apache/baremaps/database/DataMapTest.java  |   7 +-
 .../openstreetmap/xml/XmlEntityReader.java         |  10 +-
 .../apache/baremaps/openstreetmap/OsmTestData.java |  73 ++++----
 23 files changed, 439 insertions(+), 297 deletions(-)

diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/AppendOnlyLog.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/AppendOnlyLog.java
index 55664d7e..b1b525fb 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/AppendOnlyLog.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/AppendOnlyLog.java
@@ -31,8 +31,8 @@ import org.apache.baremaps.database.type.DataType;
 
 /**
  * A log of records backed by a {@link DataType} and a {@link Memory}. 
Elements are appended to the
- * buffer and can be accessed by their position in the {@link Memory}. 
Appending elements to the
- * buffer is thread-safe.
+ * log and can be accessed by their position in the {@link Memory}. Appending 
elements to the log is
+ * thread-safe.
  *
  * @param <E> The type of the data.
  */
@@ -47,7 +47,7 @@ public class AppendOnlyLog<E> implements DataCollection<E> {
   private Lock lock = new ReentrantLock();
 
   /**
-   * Constructs an append only buffer.
+   * Constructs an {@link AppendOnlyLog}.
    *
    * @param dataType the data type
    */
@@ -56,7 +56,7 @@ public class AppendOnlyLog<E> implements DataCollection<E> {
   }
 
   /**
-   * Constructs an append only buffer.
+   * Constructs an append only log.
    *
    * @param dataType the data type
    * @param memory the memory
@@ -70,7 +70,7 @@ public class AppendOnlyLog<E> implements DataCollection<E> {
   }
 
   /**
-   * Appends the value to the buffer and returns its position in the memory.
+   * Appends the value to the log and returns its position in the memory.
    *
    * @param value the value
    * @return the position of the value in the memory.
@@ -101,41 +101,32 @@ public class AppendOnlyLog<E> implements 
DataCollection<E> {
     return position;
   }
 
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean add(E e) {
-    addPositioned(e);
-    return true;
-  }
-
-
   /**
    * Returns a values at the specified position in the memory.
    *
    * @param position the position of the value
    * @return the value
    */
-  public E read(long position) {
+  public E getPositioned(long position) {
     long segmentIndex = position / segmentSize;
     long segmentOffset = position % segmentSize;
     ByteBuffer buffer = memory.segment((int) segmentIndex);
     return dataType.read(buffer, (int) segmentOffset);
   }
 
-  /**
-   * Returns the size of the log.
-   *
-   * @return the size of the log
-   */
+  /** {@inheritDoc} */
+  @Override
+  public boolean add(E e) {
+    addPositioned(e);
+    return true;
+  }
+
+  /** {@inheritDoc} */
   public long size() {
     return size;
   }
 
-  /**
-   * Clears the log.
-   */
+  /** {@inheritDoc} */
   public void clear() {
     try {
       memory.clear();
@@ -145,39 +136,30 @@ public class AppendOnlyLog<E> implements 
DataCollection<E> {
   }
 
   /**
-   * Returns an iterator over the values of the log.
+   * Returns an iterator over the values of the log, starting at the beginning 
of the log. The
+   * iterator allows to get the current position in the memory.
    * 
    * @return an iterator over the values of the log
    */
   @Override
-  public BufferIterator iterator() {
+  public AppendOnlyLogIterator iterator() {
     final long size = size();
-    return new BufferIterator(size);
+    return new AppendOnlyLogIterator(size);
   }
 
   /**
-   * Returns true if the log contains the specified value.
-   * 
-   * @param value the value
-   * @return true if the log contains the specified value
+   * An iterator over the values of the log that can be used to iterate over 
the values of the log
+   * and to get the current position in the memory.
    */
-  public boolean contains(Object value) {
-    for (E e : this) {
-      if (e.equals(value)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  public class BufferIterator implements Iterator<E> {
+  public class AppendOnlyLogIterator implements Iterator<E> {
 
     private final long size;
+
     private long index;
 
     private long position;
 
-    public BufferIterator(long size) {
+    private AppendOnlyLogIterator(long size) {
       this.size = size;
       index = 0;
       position = Long.BYTES;
@@ -221,5 +203,6 @@ public class AppendOnlyLog<E> implements DataCollection<E> {
     public long getPosition() {
       return position;
     }
+
   }
 }
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollection.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollection.java
index cbc7afc1..5452153f 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollection.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollection.java
@@ -17,13 +17,15 @@
 
 package org.apache.baremaps.database.collection;
 
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Spliterator;
-import java.util.Spliterators;
+import java.util.*;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
+/**
+ * A {@code DataCollection<E>} is a group of elements that can be iterated 
over. It is similar to a
+ * {@link java.util.Collection<E> Collection<E>}, but can hold up to {@link 
Long#MAX_VALUE}
+ * elements.
+ */
 public interface DataCollection<E> extends Iterable<E> {
 
   /**
@@ -67,6 +69,15 @@ public interface DataCollection<E> extends Iterable<E> {
     return StreamSupport.stream(spliterator(), false);
   }
 
+  /**
+   * Returns a parallel stream over the elements in the data collection.
+   *
+   * @return a parallel stream
+   */
+  default Stream<E> parallelStream() {
+    return StreamSupport.stream(spliterator(), true);
+  }
+
   /**
    * Adds a value to the data collection.
    *
@@ -77,7 +88,13 @@ public interface DataCollection<E> extends Iterable<E> {
     throw new UnsupportedOperationException();
   }
 
-  default boolean addAll(Collection<? extends E> c) {
+  /**
+   * Adds all the values in the specified collection to the data collection.
+   *
+   * @param c the collection of values to add
+   * @return true if the data collection has been modified
+   */
+  default boolean addAll(Iterable<? extends E> c) {
     boolean modified = false;
     for (E e : c) {
       if (add(e)) {
@@ -87,20 +104,11 @@ public interface DataCollection<E> extends Iterable<E> {
     return modified;
   }
 
-  default boolean remove(Object o) {
-    throw new UnsupportedOperationException();
-  }
-
-  default boolean removeAll(Collection<?> c) {
-    boolean modified = false;
-    for (Object o : c) {
-      if (remove(o)) {
-        modified = true;
-      }
-    }
-    return modified;
-  }
-
+  /**
+   * Returns true if the data collection contains the specified value.
+   *
+   * @param o the value to search for
+   */
   default boolean contains(Object o) {
     for (E e : this) {
       if (e.equals(o)) {
@@ -110,7 +118,13 @@ public interface DataCollection<E> extends Iterable<E> {
     return false;
   }
 
-  default boolean containsAll(Collection<?> c) {
+  /**
+   * Returns true if the data collection contains all the values in the 
specified collection.
+   *
+   * @param c the collection of values to search for
+   * @return true if the data collection contains all the values
+   */
+  default boolean containsAll(Iterable<?> c) {
     for (Object o : c) {
       if (!contains(o)) {
         return false;
@@ -119,6 +133,9 @@ public interface DataCollection<E> extends Iterable<E> {
     return true;
   }
 
+  /**
+   * Removes all the values from the data collection.
+   */
   void clear();
 
 }
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollectionException.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollectionException.java
index 62aa7164..5e5b835e 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollectionException.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollectionException.java
@@ -19,6 +19,7 @@ package org.apache.baremaps.database.collection;
 
 /** Signals that an exception occurred in a store. */
 public class DataCollectionException extends RuntimeException {
+
   /** Constructs a {@code DataCollectionException} with {@code null} as its 
error detail message. */
   public DataCollectionException() {}
 
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollectionMapper.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollectionMapper.java
index 70b0ecc5..42fc3bc5 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollectionMapper.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataCollectionMapper.java
@@ -41,19 +41,19 @@ public class DataCollectionMapper<S, T> implements 
DataCollection<T> {
     this.mapper = mapper;
   }
 
+  /** {@inheritDoc} */
   @Override
   public long size() {
     return collection.size();
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public Iterator<T> iterator() {
     return collection.stream().map(this.mapper).iterator();
   }
 
+  /** {@inheritDoc} */
   @Override
   public void clear() {
     collection.clear();
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataConversions.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataConversions.java
index c25c5e06..43ba12f4 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataConversions.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataConversions.java
@@ -20,8 +20,79 @@ package org.apache.baremaps.database.collection;
 import java.util.*;
 import java.util.Map.Entry;
 
+/**
+ * Utility class for converting between collections and data collections.
+ */
 public class DataConversions {
 
+  private DataConversions() {
+    // Utility class
+  }
+
+  /**
+   * Converts a {@code DataCollection} to a {@code Collection}.
+   * 
+   * @param dataCollection
+   * @return
+   * @param <E>
+   */
+  public static <E> Collection<E> asCollection(DataCollection<E> 
dataCollection) {
+    if (dataCollection instanceof DataCollectionAdapter<E>adapter) {
+      return adapter.collection;
+    } else {
+      return new CollectionAdapter<>(dataCollection);
+    }
+  }
+
+  /**
+   * Converts a {@code Collection} to a {@code DataCollection}.
+   *
+   * @param collection
+   * @return
+   * @param <E>
+   */
+  public static <E> DataCollection<E> asDataCollection(Collection<E> 
collection) {
+    if (collection instanceof CollectionAdapter<E>adapter) {
+      return adapter.collection;
+    } else {
+      return new DataCollectionAdapter<>(collection);
+    }
+  }
+
+  /**
+   * Converts a {@code DataList} to a {@code List}.
+   *
+   * @param dataList the data list
+   * @return the list
+   */
+  public static <E> List<E> asList(DataList<E> dataList) {
+    if (dataList instanceof DataListAdapter<E>adapter) {
+      return adapter.list;
+    } else {
+      return new ListAdapter<>(dataList);
+    }
+  }
+
+  /**
+   * Converts a {@code List} to a {@code DataList}.
+   *
+   * @param list the list
+   * @return the data list
+   */
+  public static <E> DataList<E> asDataList(List<E> list) {
+    if (list instanceof ListAdapter<E>adapter) {
+      return adapter.list;
+    } else {
+      return new DataListAdapter<>(list);
+    }
+  }
+
+  /**
+   * Converts a {@code DataMap} to a {@code Map}.
+   *
+   * @param dataMap the data map
+   * @return the map
+   */
   public static <K, V> Map<K, V> asMap(DataMap<K, V> dataMap) {
     if (dataMap instanceof DataMapAdapter<K, V>adapter) {
       return adapter.map;
@@ -30,6 +101,12 @@ public class DataConversions {
     }
   }
 
+  /**
+   * Converts a {@code Map} to a {@code DataMap}.
+   *
+   * @param map the map
+   * @return the data map
+   */
   public static <K, V> DataMap<K, V> asDataMap(Map<K, V> map) {
     if (map instanceof MapAdapter<K, V>adapter) {
       return adapter.map;
@@ -38,7 +115,113 @@ public class DataConversions {
     }
   }
 
-  public static class MapAdapter<K, V> extends AbstractMap<K, V> {
+  private static class CollectionAdapter<E> extends AbstractCollection<E> {
+
+    private final DataCollection<E> collection;
+    private final int size;
+
+    public CollectionAdapter(DataCollection<E> dataCollection) {
+      this.collection = dataCollection;
+      this.size = (int) dataCollection.size();
+    }
+
+    @Override
+    public int size() {
+      return size;
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+      return collection.iterator();
+    }
+  }
+
+  private static class DataCollectionAdapter<E> implements DataCollection<E> {
+
+    private final Collection<E> collection;
+
+    public DataCollectionAdapter(Collection<E> collection) {
+      this.collection = collection;
+    }
+
+    @Override
+    public long size() {
+      return collection.size();
+    }
+
+    @Override
+    public boolean add(E value) {
+      return collection.add(value);
+    }
+
+    @Override
+    public void clear() {
+      collection.clear();
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+      return collection.iterator();
+    }
+  }
+
+  private static class ListAdapter<E> extends AbstractList<E> {
+
+    private final DataList<E> list;
+    private final int size;
+
+    public ListAdapter(DataList<E> dataList) {
+      this.list = dataList;
+      this.size = (int) dataList.size();
+    }
+
+    @Override
+    public E get(int index) {
+      return list.get(index);
+    }
+
+    @Override
+    public int size() {
+      return size;
+    }
+  }
+
+  private static class DataListAdapter<E> implements DataList<E> {
+
+    private final List<E> list;
+
+    public DataListAdapter(List<E> list) {
+      this.list = list;
+    }
+
+    @Override
+    public long size() {
+      return list.size();
+    }
+
+    @Override
+    public void clear() {
+      list.clear();
+    }
+
+    @Override
+    public long addIndexed(E value) {
+      list.add(value);
+      return list.size() - 1;
+    }
+
+    @Override
+    public void set(long index, E value) {
+      list.set((int) index, value);
+    }
+
+    @Override
+    public E get(long index) {
+      return list.get((int) index);
+    }
+  }
+
+  private static class MapAdapter<K, V> extends AbstractMap<K, V> {
 
     private final DataMap<K, V> map;
     private final int size;
@@ -64,7 +247,7 @@ public class DataConversions {
     }
   }
 
-  public static class DataMapAdapter<K, V> implements DataMap<K, V> {
+  private static class DataMapAdapter<K, V> implements DataMap<K, V> {
 
     private final Map<K, V> map;
 
@@ -72,7 +255,6 @@ public class DataConversions {
       this.map = map;
     }
 
-
     @Override
     public long size() {
       return map.size();
@@ -88,11 +270,6 @@ public class DataConversions {
       return map.put(key, value);
     }
 
-    @Override
-    public V remove(K key) {
-      return map.remove(key);
-    }
-
     @Override
     public boolean containsKey(Object key) {
       return map.containsKey(key);
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataList.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataList.java
index 41f08e28..e3fac3dd 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataList.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataList.java
@@ -23,23 +23,23 @@ import java.util.Iterator;
 import java.util.NoSuchElementException;
 
 /**
- * An abstract list of data elements that can hold a large number of elements.
+ * A {@code DataList<E>} is a sequence of elements that can be iterated over 
and accessed by index.
+ * It is similar to a {@link java.util.List<E> List<E>}, but can hold up to 
{@link Long#MAX_VALUE}
+ * elements.
  *
- * @param <E> The type of the data.
+ * @param <E> The type of the elements.
  */
 public interface DataList<E> extends DataCollection<E> {
 
   /**
-   * Appends a value to the list and returns its index.
+   * Adds a value to the data list and returns its index.
    *
    * @param value the value
    * @return the index of the value.
    */
   long addIndexed(E value);
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   default boolean add(E value) {
     addIndexed(value);
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataMap.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataMap.java
index fc145df8..edc2d2ca 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataMap.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/DataMap.java
@@ -18,14 +18,17 @@
 package org.apache.baremaps.database.collection;
 
 
-import com.google.common.collect.Streams;
-import java.util.*;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map.Entry;
+import java.util.function.BiConsumer;
 
 /**
- * An abstract map of data elements that can hold a large number of elements.
+ * A {@code DataMap<E>} maps keys to values. It is similar to a {@link 
java.util.Map<K, V> Map<K,
+ * V>}, but can hold up to {@link Long#MAX_VALUE} entries.
  *
- * @param <V> The type of the elements.
+ * @param <K> The type of the keys.
+ * @param <V> The type of the values.
  */
 public interface DataMap<K, V> {
 
@@ -45,100 +48,120 @@ public interface DataMap<K, V> {
   V get(Object key);
 
   /**
-   * Returns the value associated with the specified key or null if the key is 
not present.
+   * Returns the values associated with the specified keys or null if the key 
is not present.
    *
    * @param keys the keys
    * @return the values
    */
   default List<V> getAll(List<K> keys) {
-    return Streams.stream(keys).map(this::get).toList();
+    return keys.stream().map(this::get).toList();
   }
 
   /**
-   * Associates the specified value with the specified key in the map.
-   * 
+   * Associates the specified value with the specified key in the data map.
+   *
    * @param key the key
    * @param value the value
-   * @return the previous value associated with the key, or null if there was 
no mapping for the
-   *         key.
+   * @return the previous value associated with the key, or null if there was 
no mapping for the key
    */
   V put(K key, V value);
 
   /**
-   * Removes the mapping for the specified key from the map if present.
+   * Associates the specified values with the specified keys in the data map.
    *
-   * @param key the key
-   * @return the previous value associated with the key, or null if there was 
no mapping for the
-   *         key.
+   * @param entries the entries
    */
-  V remove(K key);
+  default void putAll(Iterable<Entry<K, V>> entries) {
+    entries.forEach(entry -> put(entry.getKey(), entry.getValue()));
+  }
 
   /**
-   * Returns true if the map contains a mapping for the specified key.
+   * Returns true if the data map contains a mapping for the specified key.
    *
    * @param key the key
-   * @return true if the map contains a mapping for the key
+   * @return true if the data map contains a mapping for the key
    */
   boolean containsKey(Object key);
 
   /**
-   * Returns true if the map contains a mapping for the specified value.
+   * Returns true if the data map contains a mapping for the specified value.
    *
    * @param value the value
-   * @return true if the map contains a mapping for the value
+   * @return true if the data map contains a mapping for the value
    */
   boolean containsValue(V value);
 
   /**
-   * Clears the map.
+   * Clears the data map.
    */
   void clear();
 
   /**
-   * Returns true if the map contains no elements.
+   * Returns true if the data map contains no elements.
    * 
-   * @return true if the map contains no elements
+   * @return true if the data map contains no elements
    */
   default boolean isEmpty() {
     return size() == 0;
   }
 
   /**
-   * Returns an iterator over the keys of the map.
+   * Returns an iterator over the keys of the data map.
    *
    * @return an iterator
    */
   Iterator<K> keyIterator();
 
   /**
-   * Returns an iterator over the values of the map.
+   * Returns an iterable over the keys of the data map.
+   *
+   * @return an iterable
+   */
+  default Iterable<K> keys() {
+    return this::keyIterator;
+  }
+
+  /**
+   * Returns an iterator over the values of the data map.
    *
    * @return an iterator
    */
   Iterator<V> valueIterator();
 
   /**
-   * Returns an iterator over the entries of the map.
+   * Returns an iterable over the values of the data map.
+   *
+   * @return an iterable
+   */
+  default Iterable<V> values() {
+    return this::valueIterator;
+  }
+
+  /**
+   * Returns an iterator over the entries of the data map.
    *
    * @return an iterator
    */
   Iterator<Entry<K, V>> entryIterator();
 
-  /** {@inheritDoc} */
-  default Set<Entry<K, V>> entrySet() {
-    int size = (int) size();
-    return new AbstractSet<>() {
-
-      @Override
-      public Iterator<Entry<K, V>> iterator() {
-        return entryIterator();
-      }
-
-      @Override
-      public int size() {
-        return size;
-      }
-    };
+  /**
+   * Returns an iterable over the entries of the data map.
+   *
+   * @return an iterable
+   */
+  default Iterable<Entry<K, V>> entries() {
+    return this::entryIterator;
+  }
+
+  /**
+   * Performs the given action for each entry in the data map.
+   *
+   * @param action the action to be performed
+   */
+  default void forEach(BiConsumer<? super K, ? super V> action) {
+    for (Entry<K, V> entry : entries()) {
+      action.accept(entry.getKey(), entry.getValue());
+    }
   }
 
 }
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/FixedSizeDataList.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/FixedSizeDataList.java
index a12c9d8f..1be22276 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/FixedSizeDataList.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/FixedSizeDataList.java
@@ -26,9 +26,8 @@ import org.apache.baremaps.database.memory.OffHeapMemory;
 import org.apache.baremaps.database.type.FixedSizeDataType;
 
 /**
- * A list that can hold a large number of fixed size data elements.
- *
- * This list is backed by a memory that can be either heap, off-heap, or 
memory mapped.
+ * A data list that can hold a large number of fixed size data elements. This 
data list is backed by
+ * a memory that can be either heap, off-heap, or memory mapped.
  *
  * @param <E> The type of the elements.
  */
@@ -41,7 +40,7 @@ public class FixedSizeDataList<E> implements DataList<E> {
   private AtomicLong size;
 
   /**
-   * Constructs a list.
+   * Constructs a {@link FixedSizeDataList}.
    *
    * @param dataType the data type
    */
@@ -72,9 +71,7 @@ public class FixedSizeDataList<E> implements DataList<E> {
     dataType.write(segment, segmentOffset, value);
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public long addIndexed(E value) {
     long index = size.getAndIncrement();
@@ -82,9 +79,7 @@ public class FixedSizeDataList<E> implements DataList<E> {
     return index;
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public void set(long index, E value) {
     if (index >= size()) {
@@ -93,9 +88,7 @@ public class FixedSizeDataList<E> implements DataList<E> {
     write(index, value);
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public E get(long index) {
     long position = index * dataType.size();
@@ -105,17 +98,13 @@ public class FixedSizeDataList<E> implements DataList<E> {
     return dataType.read(segment, segmentOffset);
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public long size() {
     return size.get();
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public void clear() {
     size.set(0);
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/IndexedDataList.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/IndexedDataList.java
index 0fe65547..f2d8952f 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/IndexedDataList.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/IndexedDataList.java
@@ -22,9 +22,8 @@ package org.apache.baremaps.database.collection;
 import org.apache.baremaps.database.type.LongDataType;
 
 /**
- * A list that can hold a large number of variable size data elements.
- *
- * This list is backed by an index and a buffer that can be either heap, 
off-heap, or memory mapped.
+ * A data list that can hold a large number of variable size data elements. 
This data list is backed
+ * by an index and a buffer that can be either heap, off-heap, or memory 
mapped.
  *
  * @param <E> The type of the elements.
  */
@@ -34,9 +33,8 @@ public class IndexedDataList<E> implements DataList<E> {
 
   private final AppendOnlyLog<E> values;
 
-
   /**
-   * Constructs a list.
+   * Constructs a {@link IndexedDataList}.
    *
    * @param values the values
    */
@@ -45,7 +43,7 @@ public class IndexedDataList<E> implements DataList<E> {
   }
 
   /**
-   * Constructs a list.
+   * Constructs a {@link IndexedDataList}.
    *
    * @param index the index
    * @param values the values
@@ -55,44 +53,34 @@ public class IndexedDataList<E> implements DataList<E> {
     this.values = values;
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public long addIndexed(E value) {
     long position = values.addPositioned(value);
     return index.addIndexed(position);
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public void set(long index, E value) {
     long position = values.addPositioned(value);
     this.index.set(index, position);
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public E get(long index) {
     long position = this.index.get(index);
-    return values.read(position);
+    return values.getPositioned(position);
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public long size() {
     return index.size();
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public void clear() {
     index.clear();
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/IndexedDataMap.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/IndexedDataMap.java
index 4e1655db..9f3d6fb4 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/IndexedDataMap.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/IndexedDataMap.java
@@ -26,9 +26,8 @@ import java.util.Map;
 import java.util.Map.Entry;
 
 /**
- * A map that can hold a large number of variable size data elements.
- *
- * This map is backed by an index and a buffer that can be either heap, 
off-heap, or memory mapped.
+ * A data map that can hold a large number of variable size data elements. 
This data map is backed
+ * by an index and a buffer that can be either heap, off-heap, or memory 
mapped.
  *
  * @param <E> The type of the elements.
  */
@@ -39,7 +38,7 @@ public class IndexedDataMap<E> implements DataMap<Long, E> {
   private final AppendOnlyLog<E> values;
 
   /**
-   * Constructs a map.
+   * Constructs a {@link IndexedDataMap}.
    *
    * @param values the values
    */
@@ -48,7 +47,7 @@ public class IndexedDataMap<E> implements DataMap<Long, E> {
   }
 
   /**
-   * Constructs a map.
+   * Constructs a {@link IndexedDataMap}.
    *
    * @param index the index
    * @param values the values
@@ -58,90 +57,65 @@ public class IndexedDataMap<E> implements DataMap<Long, E> {
     this.values = values;
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public E put(Long key, E value) {
     var oldIndex = index.get(key);
     var position = values.addPositioned(value);
     index.put(key, position);
-    return oldIndex == null ? null : values.read(oldIndex);
+    return oldIndex == null ? null : values.getPositioned(oldIndex);
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public E get(Object key) {
     var position = index.get(key);
-    return position == null ? null : values.read(position);
+    return position == null ? null : values.getPositioned(position);
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public Iterator<Long> keyIterator() {
     return index.keySet().iterator();
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public Iterator<E> valueIterator() {
     return Streams.stream(keyIterator()).map(this::get).iterator();
   }
 
+  /** {@inheritDoc} */
   @Override
   public Iterator<Entry<Long, E>> entryIterator() {
     return Streams.stream(keyIterator()).map(k -> Map.entry(k, 
get(k))).iterator();
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public boolean isEmpty() {
     return index.isEmpty();
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public long size() {
     return index.size();
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public boolean containsKey(Object key) {
     return index.containsKey(key);
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public boolean containsValue(Object value) {
-    return index.values().stream().map(values::read).anyMatch(value::equals);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public E remove(Long key) {
-    return values.read(index.remove(key));
+    return 
index.values().stream().map(values::getPositioned).anyMatch(value::equals);
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public void clear() {
     index.clear();
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MemoryAlignedDataList.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MemoryAlignedDataList.java
index 931ed536..29448052 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MemoryAlignedDataList.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MemoryAlignedDataList.java
@@ -27,9 +27,8 @@ import org.apache.baremaps.database.memory.OffHeapMemory;
 import org.apache.baremaps.database.type.FixedSizeDataType;
 
 /**
- * A list that can hold a large number of fixed-size memory-aligned data 
elements.
- *
- * This list is backed by a memory that can be either heap, off-heap, or 
memory mapped.
+ * A data list that can hold a large number of fixed-size memory-aligned data 
elements. This data
+ * list is backed by a memory that can be either heap, off-heap, or memory 
mapped.
  *
  * @param <E> The type of the elements.
  */
@@ -48,7 +47,7 @@ public class MemoryAlignedDataList<E> implements DataList<E> {
   private AtomicLong size;
 
   /**
-   * Constructs a list.
+   * Constructs a {@link MemoryAlignedDataList}.
    *
    * @param dataType the data type
    */
@@ -57,7 +56,7 @@ public class MemoryAlignedDataList<E> implements DataList<E> {
   }
 
   /**
-   * Constructs a list.
+   * Constructs a {@link MemoryAlignedDataList}.
    *
    * @param dataType the data type
    * @param memory the memory
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MemoryAlignedDataMap.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MemoryAlignedDataMap.java
index 3cbd3f4f..6b45278d 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MemoryAlignedDataMap.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MemoryAlignedDataMap.java
@@ -28,7 +28,7 @@ import org.apache.baremaps.database.memory.Memory;
 import org.apache.baremaps.database.type.FixedSizeDataType;
 
 /**
- * A map that can hold a large number of fixed-size memory-aligned data 
elements.
+ * A data map that can hold a large number of fixed-size memory-aligned data 
elements.
  *
  * <p>
  * This code has been adapted from Planetiler (Apache license).
@@ -46,7 +46,7 @@ public class MemoryAlignedDataMap<E> implements DataMap<Long, 
E> {
   private final long segmentMask;
 
   /**
-   * Constructs a map.
+   * Constructs a {@link MemoryAlignedDataMap}.
    *
    * @param dataType the data type
    * @param memory the memory
@@ -90,12 +90,6 @@ public class MemoryAlignedDataMap<E> implements 
DataMap<Long, E> {
     return dataType.read(segment, segmentOffset);
   }
 
-  /** {@inheritDoc} */
-  @Override
-  public E remove(Long key) {
-    throw new UnsupportedOperationException();
-  }
-
   /** {@inheritDoc} */
   @Override
   public boolean containsKey(Object keyObject) {
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicDataMap.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicDataMap.java
index 21d22bea..25c0eb7c 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicDataMap.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicDataMap.java
@@ -27,9 +27,9 @@ import org.apache.baremaps.database.type.PairDataType;
 import org.apache.baremaps.database.type.PairDataType.Pair;
 
 /**
- * A map that can hold a large number of variable-size data elements. The 
elements must be sorted by
- * their key and inserted in a monotonic way. The elements cannot be removed 
or updated once
- * inserted.
+ * A data map that can hold a large number of variable-size data elements. The 
elements must be
+ * sorted by their key and inserted in a monotonic way. The elements cannot be 
removed or updated
+ * once inserted.
  *
  * <p>
  * This code has been adapted from Planetiler (Apache license).
@@ -46,7 +46,7 @@ public class MonotonicDataMap<E> implements DataMap<Long, E> {
   private long lastChunk = -1;
 
   /**
-   * Constructs a map with default lists for storing offsets.
+   * Constructs a {@link MonotonicDataMap} with default lists for storing 
offsets.
    *
    * @param values the buffer of values
    */
@@ -58,7 +58,7 @@ public class MonotonicDataMap<E> implements DataMap<Long, E> {
   }
 
   /**
-   * Constructs a map with default lists for storing offsets and keys.
+   * Constructs a {@link MonotonicDataMap} with default lists for storing 
offsets and keys.
    *
    * @param keys the list of keys
    * @param values the buffer of values
@@ -71,7 +71,7 @@ public class MonotonicDataMap<E> implements DataMap<Long, E> {
   }
 
   /**
-   * Constructs a map.
+   * Constructs a {@link MonotonicDataMap}.
    *
    * @param offsets the list of offsets
    * @param keys the list of keys
@@ -124,7 +124,7 @@ public class MonotonicDataMap<E> implements DataMap<Long, 
E> {
         hi = index - 1;
       } else {
         // found
-        return values.read(pair.right());
+        return values.getPositioned(pair.right());
       }
     }
     return null;
@@ -139,13 +139,13 @@ public class MonotonicDataMap<E> implements DataMap<Long, 
E> {
   /** {@inheritDoc} */
   @Override
   public Iterator<E> valueIterator() {
-    return keys.stream().map(Pair::right).map(values::read).iterator();
+    return 
keys.stream().map(Pair::right).map(values::getPositioned).iterator();
   }
 
   @Override
   public Iterator<Entry<Long, E>> entryIterator() {
     return keys.stream()
-        .map(p -> Map.entry(p.left(), values.read(p.right())))
+        .map(p -> Map.entry(p.left(), values.getPositioned(p.right())))
         .iterator();
   }
 
@@ -168,12 +168,6 @@ public class MonotonicDataMap<E> implements DataMap<Long, 
E> {
     return values.contains(value);
   }
 
-  /** {@inheritDoc} */
-  @Override
-  public E remove(Long key) {
-    throw new UnsupportedOperationException();
-  }
-
   /** {@inheritDoc} */
   @Override
   public void clear() {
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicFixedSizeDataMap.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicFixedSizeDataMap.java
index d686c047..e03f6701 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicFixedSizeDataMap.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicFixedSizeDataMap.java
@@ -26,8 +26,8 @@ import java.util.Map.Entry;
 import org.apache.baremaps.database.type.LongDataType;
 
 /**
- * A map that can hold a large number of fixed-size data elements. The 
elements must be sorted by
- * their key and inserted in a monotonic way. The elements cannot be removed 
or updated once
+ * A data map that can hold a large number of fixed-size data elements. The 
elements must be sorted
+ * by their key and inserted in a monotonic way. The elements cannot be 
removed or updated once
  * inserted.
  *
  * <p>
@@ -44,7 +44,7 @@ public class MonotonicFixedSizeDataMap<E> implements 
DataMap<Long, E> {
   private long lastChunk = -1;
 
   /**
-   * Constructs a map with default lists for storing offsets and keys.
+   * Constructs a {@link MonotonicFixedSizeDataMap} with default lists for 
storing offsets and keys.
    *
    * @param values the list of values
    */
@@ -54,7 +54,7 @@ public class MonotonicFixedSizeDataMap<E> implements 
DataMap<Long, E> {
   }
 
   /**
-   * Constructs a map.
+   * Constructs a {@link MonotonicFixedSizeDataMap}.
    *
    * @param offsets the list of offsets
    * @param keys the list of keys
@@ -108,12 +108,6 @@ public class MonotonicFixedSizeDataMap<E> implements 
DataMap<Long, E> {
     return null;
   }
 
-  /** {@inheritDoc} */
-  @Override
-  public E remove(Long key) {
-    throw new UnsupportedOperationException();
-  }
-
   /** {@inheritDoc} */
   @Override
   public long size() {
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicPairedDataMap.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicPairedDataMap.java
index 45f2ad30..b38d6d3c 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicPairedDataMap.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/collection/MonotonicPairedDataMap.java
@@ -26,9 +26,9 @@ import org.apache.baremaps.database.type.LongDataType;
 import org.apache.baremaps.database.type.PairDataType.Pair;
 
 /**
- * A map that can hold a large number of variable-size data elements. The 
elements must be sorted by
- * their key and inserted in a monotonic way. The elements cannot be removed 
or updated once
- * inserted.
+ * A data map that can hold a large number of variable-size data elements. The 
elements must be
+ * sorted by their key and inserted in a monotonic way. The elements cannot be 
removed or updated
+ * once inserted.
  */
 public class MonotonicPairedDataMap<E> implements DataMap<Long, E> {
 
@@ -37,12 +37,15 @@ public class MonotonicPairedDataMap<E> implements 
DataMap<Long, E> {
 
   private long lastChunk = -1;
 
+  /**
+   * Constructs a {@link MonotonicPairedDataMap}.
+   */
   public MonotonicPairedDataMap(MemoryAlignedDataList<Pair<Long, E>> values) {
     this(new MemoryAlignedDataList<>(new LongDataType()), values);
   }
 
   /**
-   * Constructs a map.
+   * Constructs a {@link MonotonicPairedDataMap}.
    *
    * @param offsets the list of offsets
    * @param values the buffer of values
@@ -110,6 +113,7 @@ public class MonotonicPairedDataMap<E> implements 
DataMap<Long, E> {
     return values.stream().map(Pair::right).iterator();
   }
 
+  /** {@inheritDoc} */
   @Override
   public Iterator<Entry<Long, E>> entryIterator() {
     return values.stream()
@@ -135,12 +139,6 @@ public class MonotonicPairedDataMap<E> implements 
DataMap<Long, E> {
     return values.stream().anyMatch(p -> p.right().equals(value));
   }
 
-  /** {@inheritDoc} */
-  @Override
-  public E remove(Long key) {
-    throw new UnsupportedOperationException();
-  }
-
   /** {@inheritDoc} */
   @Override
   public void clear() {
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/memory/Memory.java 
b/baremaps-core/src/main/java/org/apache/baremaps/database/memory/Memory.java
index b18dfcce..4e1eb0c6 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/memory/Memory.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/memory/Memory.java
@@ -36,6 +36,11 @@ public abstract class Memory<T extends ByteBuffer> 
implements Closeable {
 
   protected final List<T> segments = new ArrayList<>();
 
+  /**
+   * Constructs a memory with a given segment size.
+   *
+   * @param segmentSize the size of the segments
+   */
   protected Memory(int segmentSize) {
     if ((segmentSize & -segmentSize) != segmentSize) {
       throw new IllegalArgumentException("The segment size must be a power of 
2");
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/database/memory/MemoryException.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/database/memory/MemoryException.java
index f6868299..350bb561 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/database/memory/MemoryException.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/database/memory/MemoryException.java
@@ -19,6 +19,7 @@ package org.apache.baremaps.database.memory;
 
 /** Signals that an exception occurred in a memory. */
 public class MemoryException extends RuntimeException {
+
   /** Constructs a {@link MemoryException} with {@code null} as its error 
detail message. */
   public MemoryException() {}
 
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 671ca1b2..768f283b 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
@@ -31,7 +31,6 @@ import java.util.Spliterator;
 import java.util.Spliterators;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
-import org.apache.baremaps.openstreetmap.OsmReader;
 
 /**
  * A reader for the Geonames database.
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/storage/postgres/PostgresDataTable.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/storage/postgres/PostgresDataTable.java
index 88374ad5..7cd18799 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/storage/postgres/PostgresDataTable.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/storage/postgres/PostgresDataTable.java
@@ -112,7 +112,7 @@ public class PostgresDataTable implements DataTable {
    * {@inheritDoc}
    */
   @Override
-  public boolean addAll(Collection<? extends DataRow> rows) {
+  public boolean addAll(Iterable<? extends DataRow> rows) {
     try (var connection = dataSource.getConnection();
         var statement = connection.prepareStatement(insert(rowType))) {
       for (var row : rows) {
diff --git 
a/baremaps-core/src/test/java/org/apache/baremaps/database/AppendOnlyLogTest.java
 
b/baremaps-core/src/test/java/org/apache/baremaps/database/AppendOnlyLogTest.java
index 8b5d14ab..d651a9db 100644
--- 
a/baremaps-core/src/test/java/org/apache/baremaps/database/AppendOnlyLogTest.java
+++ 
b/baremaps-core/src/test/java/org/apache/baremaps/database/AppendOnlyLogTest.java
@@ -40,7 +40,7 @@ class AppendOnlyLogTest {
       assertEquals(Long.BYTES + (i << 2), collection.addPositioned(i));
     }
     for (int i = 0; i < 1 << 20; i++) {
-      assertEquals(i, collection.read(Long.BYTES + (i << 2)));
+      assertEquals(i, collection.getPositioned(Long.BYTES + (i << 2)));
     }
   }
 
@@ -60,7 +60,7 @@ class AppendOnlyLogTest {
       values.add(value);
     }
     for (int i = 0; i < positions.size(); i++) {
-      var value = collection.read(positions.get(i));
+      var value = collection.getPositioned(positions.get(i));
       assertEquals(values.get(i), value);
     }
   }
diff --git 
a/baremaps-core/src/test/java/org/apache/baremaps/database/DataMapTest.java 
b/baremaps-core/src/test/java/org/apache/baremaps/database/DataMapTest.java
index f6e82feb..0f26cb7b 100644
--- a/baremaps-core/src/test/java/org/apache/baremaps/database/DataMapTest.java
+++ b/baremaps-core/src/test/java/org/apache/baremaps/database/DataMapTest.java
@@ -123,12 +123,13 @@ class DataMapTest {
   @ParameterizedTest
   @MethodSource("mapProvider")
   void entrySet(DataMap<Long, Long> map) {
-    var set = new HashSet<Entry<Long, Long>>();
+    var set1 = new HashSet<Entry<Long, Long>>();
     for (long i = 0; i < 1000; i++) {
-      set.add(Map.entry(i, i));
+      set1.add(Map.entry(i, i));
       map.put(i, i);
     }
-    assertEquals(set, map.entrySet());
+    var set2 = DataConversions.asMap(map).entrySet();
+    assertEquals(set1, set2);
   }
 
   @ParameterizedTest
diff --git 
a/baremaps-openstreetmap/src/main/java/org/apache/baremaps/openstreetmap/xml/XmlEntityReader.java
 
b/baremaps-openstreetmap/src/main/java/org/apache/baremaps/openstreetmap/xml/XmlEntityReader.java
index 40bb3d1a..0645ae28 100644
--- 
a/baremaps-openstreetmap/src/main/java/org/apache/baremaps/openstreetmap/xml/XmlEntityReader.java
+++ 
b/baremaps-openstreetmap/src/main/java/org/apache/baremaps/openstreetmap/xml/XmlEntityReader.java
@@ -19,6 +19,8 @@ package org.apache.baremaps.openstreetmap.xml;
 
 
 
+import static 
org.apache.baremaps.openstreetmap.stream.ConsumerUtils.consumeThenReturn;
+
 import java.io.InputStream;
 import java.util.List;
 import java.util.Map;
@@ -27,9 +29,9 @@ import java.util.stream.StreamSupport;
 import org.apache.baremaps.openstreetmap.OsmReader;
 import org.apache.baremaps.openstreetmap.function.CoordinateMapBuilder;
 import org.apache.baremaps.openstreetmap.function.EntityGeometryBuilder;
+import org.apache.baremaps.openstreetmap.function.EntityProjectionTransformer;
 import org.apache.baremaps.openstreetmap.function.ReferenceMapBuilder;
 import org.apache.baremaps.openstreetmap.model.Entity;
-import org.apache.baremaps.openstreetmap.stream.ConsumerUtils;
 import org.locationtech.jts.geom.Coordinate;
 
 /** A utility class for parsing an OpenStreetMap XML file. */
@@ -92,10 +94,12 @@ public class XmlEntityReader implements OsmReader<Entity> {
       var coordinateMapBuilder = new CoordinateMapBuilder(coordinateMap);
       var referenceMapBuilder = new ReferenceMapBuilder(referenceMap);
       var entityGeometryBuilder = new EntityGeometryBuilder(coordinateMap, 
referenceMap);
+      var entityProjectionTransformer = new EntityProjectionTransformer(4326, 
srid);
       var entityHandler = coordinateMapBuilder
           .andThen(referenceMapBuilder)
-          .andThen(entityGeometryBuilder);
-      entities = entities.map(ConsumerUtils.consumeThenReturn(entityHandler));
+          .andThen(entityGeometryBuilder)
+          .andThen(entityProjectionTransformer);
+      entities = entities.map(consumeThenReturn(entityHandler));
     }
     return entities;
   }
diff --git 
a/baremaps-openstreetmap/src/test/java/org/apache/baremaps/openstreetmap/OsmTestData.java
 
b/baremaps-openstreetmap/src/test/java/org/apache/baremaps/openstreetmap/OsmTestData.java
index da7479b2..d45f3253 100644
--- 
a/baremaps-openstreetmap/src/test/java/org/apache/baremaps/openstreetmap/OsmTestData.java
+++ 
b/baremaps-openstreetmap/src/test/java/org/apache/baremaps/openstreetmap/OsmTestData.java
@@ -17,6 +17,8 @@
 
 package org.apache.baremaps.openstreetmap;
 
+import static org.apache.baremaps.openstreetmap.TestFiles.resolve;
+
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -42,8 +44,6 @@ import 
org.testcontainers.shaded.com.fasterxml.jackson.databind.DeserializationF
 import org.testcontainers.shaded.com.fasterxml.jackson.databind.JsonNode;
 import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;
 
-import static org.apache.baremaps.openstreetmap.TestFiles.resolve;
-
 
 public class OsmTestData {
 
@@ -261,43 +261,44 @@ public class OsmTestData {
     }
   }
 
-    /**
-     * A transformer that rounds the coordinates of a geometry to a given 
precision.
-     */
-    public static class RoundingTransformer extends GeometryTransformer {
+  /**
+   * A transformer that rounds the coordinates of a geometry to a given 
precision.
+   */
+  public static class RoundingTransformer extends GeometryTransformer {
 
-      private int precision;
+    private int precision;
 
-      /**
-       * Constructs a transformer that rounds the coordinates of a geometry to 
a given precision.
-       *
-       * @param precision the precision
-       */
-      public RoundingTransformer(int precision) {
-        this.precision = precision;
-      }
+    /**
+     * Constructs a transformer that rounds the coordinates of a geometry to a 
given precision.
+     *
+     * @param precision the precision
+     */
+    public RoundingTransformer(int precision) {
+      this.precision = precision;
+    }
 
-      /**
-       * Rounds the coordinates of a geometry to a given precision.
-       *
-       * @param sequence the coordinate sequence
-       * @param parent the parent geometry
-       * @return the geometry
-       */
-      @Override
-      protected CoordinateSequence transformCoordinates(CoordinateSequence 
sequence, Geometry parent) {
-        CoordinateSequence rounded = super.transformCoordinates(sequence, 
parent);
-        for (int i = 0; i < rounded.size(); i++) {
-          double roundedX =
-              Math.round(rounded.getOrdinate(i, CoordinateSequence.X) * 
Math.pow(10, precision))
-                  / Math.pow(10, precision);
-          double roundedY =
-              Math.round(rounded.getOrdinate(i, CoordinateSequence.Y) * 
Math.pow(10, precision))
-                  / Math.pow(10, precision);
-          rounded.setOrdinate(i, CoordinateSequence.X, roundedX);
-          rounded.setOrdinate(i, CoordinateSequence.Y, roundedY);
-        }
-        return rounded;
+    /**
+     * Rounds the coordinates of a geometry to a given precision.
+     *
+     * @param sequence the coordinate sequence
+     * @param parent the parent geometry
+     * @return the geometry
+     */
+    @Override
+    protected CoordinateSequence transformCoordinates(CoordinateSequence 
sequence,
+        Geometry parent) {
+      CoordinateSequence rounded = super.transformCoordinates(sequence, 
parent);
+      for (int i = 0; i < rounded.size(); i++) {
+        double roundedX =
+            Math.round(rounded.getOrdinate(i, CoordinateSequence.X) * 
Math.pow(10, precision))
+                / Math.pow(10, precision);
+        double roundedY =
+            Math.round(rounded.getOrdinate(i, CoordinateSequence.Y) * 
Math.pow(10, precision))
+                / Math.pow(10, precision);
+        rounded.setOrdinate(i, CoordinateSequence.X, roundedX);
+        rounded.setOrdinate(i, CoordinateSequence.Y, roundedY);
       }
+      return rounded;
     }
+  }
 }

Reply via email to