# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Spring Boot CLI application that queries PostgreSQL PostGIS spatial data and converts it to ESRI shapefiles. The application processes inference results from the KAMCO database and generates geographic shapefiles for visualization in GIS applications. ## Build and Run Commands ### Build ```bash ./gradlew build ``` ### Run Application ```bash ./gradlew bootRun ``` Or run the built JAR: ```bash java -jar build/libs/makesample-1.0.0.jar ``` ### Code Formatting Apply Google Java Format (2-space indentation) before committing: ```bash ./gradlew spotlessApply ``` Check formatting without applying: ```bash ./gradlew spotlessCheck ``` ## Architecture ### Processing Pipeline The application follows a layered architecture with a linear data flow: 1. **CLI Entry** (`ConverterCommandLineRunner`) → Reads configuration and initiates batch processing 2. **Service Orchestration** (`ShapefileConverterService`) → Coordinates the conversion workflow for each map_id 3. **Data Access** (`InferenceResultRepository`) → Queries PostGIS database and converts WKT to JTS geometries 4. **Geometry Conversion** (`GeometryConverter`) → Converts PostGIS WKT format to JTS Geometry objects 5. **Shapefile Writing** (`ShapefileWriter`) → Uses GeoTools to generate shapefile artifacts (.shp, .shx, .dbf, .prj) ### Key Design Points **Geometry Handling**: The application uses a two-step geometry conversion process: - PostGIS returns geometries as WKT (Well-Known Text) via `ST_AsText(geometry)` - `GeometryConverter` parses WKT to JTS `Geometry` objects - `ShapefileWriter` uses JTS geometries with GeoTools to write shapefiles **Batch Processing**: Configuration in `application.yml` drives batch execution: - Multiple `map-ids` processed sequentially (if specified) - If `map-ids` is null/empty, creates a merged shapefile for all batch-ids - Each map_id filtered by `batch-ids` array - Output directory structure: `{output-base-dir}/{inference-id}/{map-id}/` or `{output-base-dir}/{inference-id}/merge/` for merged mode - Separate output directory created for each map_id **Shapefile Constraints**: The application validates that all geometries for a single shapefile are homogeneous (same type) because shapefiles cannot contain mixed geometry types. This validation happens in `ShapefileConverterService.validateGeometries()`. **Feature Schema**: GeoTools requires explicit geometry field setup: - Default geometry field named `the_geom` (not `geometry`) - Field names truncated to 10 characters for DBF format compatibility - Geometry type determined from first valid geometry in result set ## Configuration Primary configuration in `src/main/resources/application.yml`: ```yaml converter: inference-id: 'D5E46F60FC40B1A8BE0CD1F3547AA6' # Inference ID (used for output folder structure) map-ids: ['35813030'] # List of map_ids to process (text type), omit for merged shapefile batch-ids: [252, 253, 257] # Batch ID array filter output-base-dir: '/kamco-nfs/dataset/export/' # Base directory for shapefile output crs: 'EPSG:5186' # Korean 2000 / Central Belt CRS ``` Database connection configured via standard Spring Boot datasource properties. ## Database Integration ### Query Pattern The repository uses `PreparedStatementCreator` to handle PostgreSQL array parameters: ```sql WHERE batch_id = ANY(?) AND map_id = ? ``` The `ANY(?)` clause requires creating a PostgreSQL array using `Connection.createArrayOf("bigint", ...)`. ### Field Mapping Database columns are mapped to shapefile fields with Korean naming: | Database Column | Shapefile Field | |-----------------|-----------------| | uid | uid | | map_id | map_id | | probability | chn_dtct_prob | | before_year | cprs_yr | | after_year | crtr_yr | | before_c | bf_cls_cd | | before_p | bf_cls_prob | | after_c | af_cls_cd | | after_p | af_cls_prob | | geometry | the_geom | ### Coordinate Reference System All geometries use **EPSG:5186** (Korean 2000 / Central Belt). The PostGIS geometry column is defined as `geometry(Polygon, 5186)`, and this CRS is preserved in the output shapefile's `.prj` file via GeoTools CRS encoding. ## Dependencies Key libraries and their roles: - **GeoTools 30.0**: Shapefile generation (`gt-shapefile`, `gt-referencing`, `gt-epsg-hsql`) - **JTS 1.19.0**: Java Topology Suite for geometry representation - **PostGIS JDBC 2.5.1**: PostgreSQL spatial extension support - **Spring Boot 3.5.7**: Framework for DI, JDBC, and configuration Note: `javax.media:jai_core` is excluded in `build.gradle` to avoid conflicts.