# GisConverter.Lib.Models Canonical model types and small helpers used across the conversion library. This document explains intent, key types, usage patterns, testing guidance and troubleshooting notes for model types such as `ConversionResult`, `ConversionStatus`, `FileExtension` and `FileExtensionHelpers`. Targets - Library: .NET Standard 2.1 (compatible with .NET 9 hosts used by the ConsoleApp and tests). Overview Keep domain value types and deterministic helpers centralized so converters and orchestration code can rely on consistent semantics for extension mapping, result reporting and lightweight option passing. Models are intentionally small, immutable where appropriate, and easy to reason about in unit and integration tests. Key types - `ConversionResult` - Immutable carrier returned by converters to represent success or failure. - Create via helpers: `ConversionResult.Success(string?)` and `ConversionResult.Failure(string?)`. - Contains: `Status` (`ConversionStatus`), `Message` (human-readable), and `TimestampUtc` (diagnostic metadata). - Equality semantics intentionally ignore `TimestampUtc` so logical comparisons in tests remain stable. - `ConversionStatus` - Enum representing the outcome: `Success` or `Failure`. - `FileExtension` (enum) and `FileExtensionHelpers` - Canonical enum of supported output file types (example values: `GeoJson`, `Shapefile`, `Csv`, etc.). - `FileExtensionHelpers.FromOption(string option)` maps a canonical option string to a `FileExtension?`. - `FileExtensionHelpers.ToDotExtension(FileExtension ext)` returns the dot-prefixed extension (for example `.geojson`). - Use these helpers as the authoritative source when constructing or asserting filenames in code and tests. Design notes - Immutability and small surface - `ConversionResult` is immutable after creation. This reduces surprises when results are passed between components and simplifies reasoning in tests. - Equality and diagnostics - `TimestampUtc` is included for diagnostic display but excluded from equality and hash computation by design. Logical equality focuses on `Status` and `Message` so tests that compare results across processes or runs are stable. - Hash codes - Hash code implementations use unchecked arithmetic to produce a compact integer; this is idiomatic and not relied upon for persistence or cross-process comparison. Usage patterns - Returning results from converters - if (error) return ConversionResult.Failure("Missing companion files (.shx/.dbf)"); return ConversionResult.Success($"Converted to {targetOption}; output: {outputPath}") - - Building canonical filenames - var maybeExt = FileExtensionHelpers.FromOption(gisTargetFormatOption); var dotExt = FileExtensionHelpers.ToDotExtension(maybeExt ?? FileExtension.Shapefile); var fileName = $"output_{DateTime.UtcNow:yyyyMMdd_HHmmss}{dotExt}"; Testing guidance - Assert on logical result semantics - Prefer `Assert.Equal(ConversionStatus.Success, result.Status)` and substring checks on `result.Message`. - Avoid asserting on `TimestampUtc` or exact message formatting unless the test specifically targets that behavior. - Use `FileExtensionHelpers` in tests - Compute expected suffixes via `FileExtensionHelpers.ToDotExtension(...)` instead of hard-coding strings. This keeps tests aligned with production mappings. - Creating expected `ConversionResult` - Use the factory helpers `Success`/`Failure` to build expected results for mocks and fakes so tests mirror production representation. Example assertions var res = converter.Convert(...); Assert.Equal(ConversionStatus.Success, res.Status); Assert.Contains("Converted to GeoJson", res.Message, StringComparison.OrdinalIgnoreCase); var ext = FileExtensionHelpers.FromOption("GeoJson"); var dot = FileExtensionHelpers.ToDotExtension(ext.Value); Assert.True(Directory.GetFiles(outputFolder, "*" + dot, SearchOpt Extending the model surface When adding a new `FileExtension` value: 1. Add the enum value to `FileExtension`. 2. Update `FileExtensionHelpers.FromOption` and `ToDotExtension` to include mappings and the dot extension. 3. Add unit tests covering mapping and any downstream behaviors that depend on the extension. Notes on MapInfo / MIF recognition `FileExtensionHelpers.FromOption` recognizes several aliases for MapInfo interchange formats. Supported inputs include (case-insensitive): - `"mapinfointerchange"`, `"mapinfo"`, `"mif"`, `"mid"` which all map to `FileExtension.MapInfoInterchange`. This ensures tests and CLI users specifying `mif`, `mid` or `mapinfo` are routed consistently. Troubleshooting - Unexpected `ConversionResult` inequality - Confirm `Message` strings match exactly (ordinal equality); if messages include timestamps or variable data prefer substring checks. - Missing expected output files in integration tests - Use `FileExtensionHelpers.ToDotExtension(...)` to compute the extension expected by the converter under test and search the output tree for matches rather than assuming exact filename patterns. - Changes to extension mappings - If you change or rename a canonical file extension mapping update corresponding tests and README notes so consumers remain consistent. Contact and maintenance - When making changes to model semantics (equality, added fields, or extension mappings) update unit tests and this README to document the rationale. - Keep the model surface small — prefer adding specific option objects or converters rather than inflating `ConversionResult` with extra fields unless necessary.