Class ShapefileCountryLoader

java.lang.Object
edu.cnu.mdi.mapping.loader.ShapefileCountryLoader
All Implemented Interfaces:
ICountryLoader

public final class ShapefileCountryLoader extends Object implements ICountryLoader
Loads GeoJsonCountryLoader.CountryFeature instances from an ESRI Shapefile set (.shp + .dbf) without any third-party dependencies.

Expected shapefile schema

The .dbf attribute table must contain at minimum:

  • ADMIN (or NAME / NAME_LONG) — the administrative / country name, e.g. "United States of America".
  • ISO_A3 (or ADM0_A3 / GU_A3) — the ISO 3166-1 alpha-3 code, e.g. "USA".

Both fields are tried in priority order; the first non-empty value found is used. Features where both the name and code fields are absent or empty are silently skipped.

Supported geometry types

Only ShapefileGeometryReader.TYPE_POLYGON records are used. Records of other types are silently skipped. Country shapefiles (e.g. Natural Earth ne_10m_admin_0_countries.shp) use Polygon geometry exclusively.

Ring handling

All rings (parts) within a Polygon record are included — outer shells and interior holes alike. The CountryRenderer fills all rings, which is visually correct for the typical use case. Callers that need to distinguish shells from holes can use ShapefileGeometryReader.isClockwise(List).

Coordinate assumptions

Input coordinates must be WGS84 or NAD83/GRS80 geographic degrees (longitude, latitude order). NAD83 is treated as WGS84 without datum transformation. A companion .prj, when present, is validated and incompatible or unrecognized coordinate systems are rejected. If it is absent, WGS84 is assumed. Coordinates are converted to radians and longitude is wrapped to (-π, π] before being stored.

Multi-record countries

Natural Earth shapefiles use one Polygon record per country, so each shapefile record maps to exactly one GeoJsonCountryLoader.CountryFeature. The parts (rings) within that record become the feature's polygon list, which is equivalent to the ring list from a GeoJSON MultiPolygon.

File layout contract

The .dbf file is assumed to have the same base name and parent directory as the .shp file. Given a path /data/countries.shp, the companion file is expected at /data/countries.dbf. An IOException is thrown if the companion file is not found.

Usage


 ICountryLoader loader = new ShapefileCountryLoader();
 List<GeoJsonCountryLoader.CountryFeature> features =
         loader.load(Path.of("/data/ne_10m_admin_0_countries.shp"));
 mapView.setCountries(features);
 

This class is stateless and thread-safe; a single instance may be reused across multiple load(java.nio.file.Path) calls.

  • Constructor Details

    • ShapefileCountryLoader

      public ShapefileCountryLoader()
  • Method Details

    • load

      Loads country features from the given filesystem path.

      The path may point to the primary file of a multi-file format (e.g. the .shp file of a shapefile set) or to a self-contained file (e.g. a .geojson file). Implementations are responsible for locating any companion files (e.g. .dbf, .shx) relative to the supplied path.

      Opens path as the .shp geometry file and derives the .dbf attribute file path by replacing the extension. Both files are read sequentially; the record order in each file must match (which is guaranteed by the shapefile specification).

      Specified by:
      load in interface ICountryLoader
      Parameters:
      path - path to the .shp file; the companion .dbf must exist in the same directory with the same base name
      Returns:
      unmodifiable list of country features; never null
      Throws:
      IOException - if either file cannot be opened, the files have differing record counts, or a geometry error occurs
    • loadFromResource

      public List<GeoJsonCountryLoader.CountryFeature> loadFromResource(String resourcePath)
      Loads country features from a classpath resource.

      The resource path must be absolute (begin with /) so that Class.getResourceAsStream(String) resolves it correctly. For multi-file formats this method may not be supportable (e.g. a shapefile set cannot be fully represented as a single classpath resource); in that case implementations should throw UnsupportedOperationException with a clear message.

      Shapefiles are multi-file formats and cannot be loaded from a single classpath resource. This method always throws UnsupportedOperationException. Use load(Path) with a filesystem path instead.

      Specified by:
      loadFromResource in interface ICountryLoader
      Parameters:
      resourcePath - absolute classpath resource path; must not be null
      Returns:
      unmodifiable list of country features; never null
      Throws:
      UnsupportedOperationException - always