---
title: SAIF.Framework.Common.Files architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-09-15
library: SAIF.Framework.Common.Files
reference_type: package
---

# SAIF.Framework.Common.Files architecture

`SAIF.Framework.Common.Files` (project folder `Common\SAIF.Common.Files`, root namespace `SAIF.Common.Files`) is a .NET Framework 4.6.2 class library containing two cohesive, mutually independent subsystems — an attribute/fluent-configuration-driven flat-file reader/writer and an ASC X12 EDI object model — that share only the `IParser<T>` contract and a dependency on the `SAIF.Framework.Common` package.

## Responsibilities
- Read and write delimited (CSV, tab-delimited, custom-delimiter) and fixed-width flat files by mapping file rows to POCO record types via declarative attributes or a fluent, code-first configuration API.
- Model, parse, build, and serialise ASC X12 EDI interchange files, including the envelope hierarchy (interchange → functional group → transaction set → hierarchical transaction → hierarchical level) and ~40 strongly-typed segment classes for healthcare transactions (837 claim, 835 remittance, 277 claim status, 997/999 acknowledgement)*.
- Provide a shared, minimal `IParser<T>` contract (`List<T> Parse(string)`) used by both the flat-file record parsing path and the EDI segment/element parsers.
- Delegate cross-cutting utility behaviour (sequential indexing, argument validation, string/enumerable/expression helpers) to the same-repo `SAIF.Framework.Common` package rather than reimplementing it.

## Component boundaries
- **Flat-file subsystem (`SAIF.Common.Files.Core`)** — a reflection- and attribute-driven mapper between delimited/fixed-width text lines and POCO record types.
  - *Declaration layer* (`Core\Attributes\`): `FormatBase` and concrete attributes (`Csv`, `TabDelimited`, `DelimitedBy`, `FixedFormat`, `DelimitedLayout`, `FixedLayout`) declare format and per-property layout.
  - *Configuration layer* (`Core\Configurations\`): `FileConfiguration`/`FileConfiguration<T>`, `FileRecordLayout`, and `FileLayoutBuilder` hold the runtime layout model and expose an alternative fluent (code-first) configuration path.
  - *Engine layer* (`Core\FileReader.cs`, `Core\FileWriter.cs`): static generic classes that discover configurations, prepare `Microsoft.VisualBasic.FileIO.TextFieldParser`, and iterate/build records. Both privately re-implement an identical attribute-scan method (`GetFileConfigurations()`), which is duplicated rather than shared.*
  - *Record model* (`Core\Record.cs`, `TabDelimitedRecord.cs`, `Field.cs`): `Record`, `TabDelimitedRecord`, and `Field` carry the raw `Value`/`Index` data.
- **EDI subsystem (`SAIF.Common.Files.Edi` and nested `Edi.Core.*` / `Edi.Segments`)** — an object model over ASC X12 interchange files.
  - *Entry/facade*: `EdiManager.File()` → `IEdiFileBuilder`/`EdiFileBuilder`; `.Path(path).Read()` / `.Write(file)` is the sanctioned entry point for file IO.
  - *IO layer* (`Edi\Core\Readers`, `Edi\Core\Writers`): `EdiFileReader` and `EdiFileWriter`.
  - *Lexical parsing layer* (`Edi\Core\Parsers`): `EdiSegmentParser` → `EdiDataElementParser` → `EdiCompositeDataElementParser`, cascading on `~`, `*`, and `:` respectively.
  - *Structural parsing layer*: `EdiGroupParser` converts a flat, index-ordered segment list into the X12 envelope hierarchy (file → functional groups → transaction sets → hierarchical transactions → hierarchical levels).
  - *Domain model* (`SAIF.Common.Files.Edi`): `EdiFile`, `EdiSegment`, `EdiElement`, `SegmentGroup`, `FunctionalGroup`, `TransactionSet`, `HierarchialTransaction`, `HierarchialLevel`.
  - *Builders* (`Edi\Core\Builders`): `SegmentBuilder` is the only writer of element indexes; `EdiRecordBuilder` is the only serialiser.
  - *Typed segment layer* (`Edi\Segments`): ~43 typed segment classes implementing `ISegmentData` (symmetric `Build()`/`Fill()`), depending on the element model but never on the parsers or on IO.
- **Shared dependency boundary**: both subsystems depend on the same-repo `SAIF.Framework.Common` NuGet package for `Sequence`, `Enforce`, and string/enumerable/expression extensions, but do not depend on each other beyond the shared `IParser<T>` contract.

## Interaction model
- The domain model never performs file IO itself; IO is isolated in `Edi\Core\Readers`/`Edi\Core\Writers` and `Core\FileReader`/`FileWriter`.
- The typed segment layer depends on the element model but never on the parsers or on IO.
- `EdiFile` is the one place where the model calls back into a parser (`EdiGroupParser.CreateFunctionalGroups`) — a lazy-initialisation/cycle point between the model and parser layers.
- Reading an EDI file: `EdiManager.File().Path(p).Read()` → `EdiFileReader.Read()` concatenates all lines into one continuous string → `EdiSegmentParser.Parse` → cascading element/composite parsers → `EdiFile.SetSegments` → `EdiFile.RefreshGroupings()` builds the header/trailer and (when `ISA`/`IEA`/`GS`/`GE` are all present) the functional-group hierarchy via `EdiGroupParser`.
- Writing an EDI file: typed segments produce elements via `ISegmentData.Build()`; `SegmentBuilder` assembles ordered elements (rejecting a duplicate identifying element at index 0, omitting nulls); `EdiRecordBuilder` serialises segments/elements to text, preserving skipped-element ordinals with `*` placeholders; `EdiFileWriter` writes the result as a single `~`-terminated line, overwriting any existing file.
- Reading a typed flat file: `FileReader<TRecord>.Read` discovers `FormatBase`/layout attributes on `TRecord`, selects a configuration (single, or the one flagged `IsDefault`), prepares `TextFieldParser` accordingly, then iterates rows and builds each record via the layout's readable properties, converters, and the delegated `Sequence` indexer.
- Writing a typed flat file: `FileWriter<TRecord>.Write` performs the same configuration discovery, then serialises an optional header record and each data record through writable layouts, converters, and fixed-width alignment/padding.
- Both subsystems' parser/reader classes are single-use instances — each parser instance carries its own results list and index sequence.*

## Architecture diagram
The following diagram shows the two independent subsystems and their shared dependency on `SAIF.Framework.Common`.

```mermaid
flowchart TD
  subgraph FlatFile["Flat-file subsystem<br>(SAIF.Common.Files.Core)"]
    Attr["Attributes<br>Csv / TabDelimited /<br>DelimitedBy / FixedFormat<br>DelimitedLayout / FixedLayout"]
    Cfg["Configurations<br>IFileConfiguration /<br>FileConfiguration&lt;T&gt;<br>FileRecordLayout / FileLayoutBuilder"]
    RW["FileReader&lt;TRecord&gt; /<br>FileWriter&lt;TRecord&gt;<br>FileReader (untyped)"]
    Rec["Record model<br>IRecord / Record / IDelimitedRecord<br>TabDelimitedRecord / Field"]
    Attr --> Cfg
    Cfg --> RW
    RW --> Rec
    RW --> TFP["Microsoft.VisualBasic.FileIO.<br>TextFieldParser"]
  end
  subgraph Edi["EDI subsystem (SAIF.Common.Files.Edi)"]
    Mgr["EdiManager / EdiFileBuilder"]
    IO["EdiFileReader / EdiFileWriter"]
    Parse["Parsers<br>EdiSegmentParser / EdiDataElementParser<br>EdiCompositeDataElementParser<br>EdiGroupParser"]
    Model["Domain model<br>EdiFile / EdiSegment / EdiElement<br>SegmentGroup / FunctionalGroup<br>TransactionSet / HierarchialTransaction<br>HierarchialLevel"]
    Build["Builders<br>SegmentBuilder / EdiRecordBuilder"]
    Seg["Typed segments (ISegmentData)<br>ISA GS ST BHT HL CLP SVC TRN,<br>and 35 more (see API reference)"]
    Mgr --> IO
    IO --> Parse
    Parse --> Model
    Seg --> Build
    Build --> Model
    Model --> Seg
    IO --> Build
  end
  Common["SAIF.Framework.Common (NuGet, same-repo)<br>Sequence / Enforce /<br>string + enumerable +<br>expression extensions"]
  FlatFile --> Common
  Edi --> Common
```

## Sequence diagram
The following diagram shows the primary read/write sequence for an EDI interchange file, from the facade entry point through parsing and grouping.

```mermaid
sequenceDiagram
	participant Caller
	participant EdiManager
	participant EdiFileBuilder
	participant EdiFileReader
	participant EdiSegmentParser
	participant EdiFile
	participant EdiGroupParser
	Caller->>EdiManager: File()
	EdiManager-->>Caller: IEdiFileBuilder
	Caller->>EdiFileBuilder: Path(path).Read()
	EdiFileBuilder->>EdiFileReader: Read()
	EdiFileReader->>EdiFileReader: File.ReadAllLines + concatenate
	EdiFileReader->>EdiSegmentParser: Parse(fileData)
	EdiSegmentParser-->>EdiFileReader: List<IEdiSegment>
	EdiFileReader->>EdiFile: SetSegments(segments)
	EdiFile->>EdiFile: RefreshGroupings()
	EdiFile->>EdiGroupParser: CreateFunctionalGroups(this)
	EdiGroupParser-->>EdiFile: IFunctionalGroupContainer
	EdiFileReader-->>EdiFileBuilder: EdiFile
	EdiFileBuilder-->>Caller: EdiFile
```

## Design constraints
- `DateMaker` is declared in namespace `SAIF.Common` despite living under `Edi\Core\`, so it appears to consumers as part of the base `SAIF.Common` namespace rather than the EDI subsystem.*
- `DateTimeBuilder` (internal, `Edi\Core\Builders\`) duplicates `DateMaker.MakeDateTime` and is never called from live code — dead code.*
- `FileFormats.MultipleRecord` is declared but never handled by `PrepareParser` or any writer branch — an unimplemented format.
- `IEdiEntity`, `IDataElementBuilder`, `Areas`, `RequirementDesignator`, `RelationalCondition`, `DataElementType`, `SegmentGroupType` are declared but not referenced by any live code in this library — reserved/unused contracts.*
- No type in this library derives from a BOF base class (`clsBusinessBase`, `clsBusinessCollectionBase`, `AppManager`), and none derives from an NHibernate, Autofac, or console-framework base type.
- Nothing in the library depends on configuration files, a database, a service container, or an identity/authorization API — configuration, security/authorization, and database interactions were all found to be none.
- The library ships its own C# source under `src` via its `.nuspec` (`<files><file src="**\*.cs" exclude="packages\**\*.*;obj\**\*.*" target="src"/></files>`), and `IncludeReferencedProjects = true` has no additional bundling effect because the `.csproj` declares no `<ProjectReference>` elements; `SAIF.Framework.Common` is consumed purely as a package dependency.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [API reference](api/index.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts.

## Sources
- Common\SAIF.Common.Files\SAIF.Framework.Common.Files.csproj
- Common\SAIF.Common.Files\Core\FileReader.cs
- Common\SAIF.Common.Files\Core\FileWriter.cs
- Common\SAIF.Common.Files\Edi\EdiManager.cs
- Common\SAIF.Common.Files\Edi\EdiFile.cs
- Common\SAIF.Common.Files\Edi\Core\Readers\EdiFileReader.cs
- Common\SAIF.Common.Files\Edi\Core\Writers\EdiFileWriter.cs
- Common\SAIF.Common.Files\Edi\Core\Parsers\EdiSegmentParser.cs
- Common\SAIF.Common.Files\Edi\Core\Parsers\EdiGroupParser.cs
- Common\SAIF.Common.Files\Edi\Core\Builders\SegmentBuilder.cs
- Common\SAIF.Common.Files\Edi\Core\Builders\EdiRecordBuilder.cs
- Common\SAIF.Common.Files\Edi\Core\DateMaker.cs
- Common\SAIF.Common.Files\Edi\Core\Builders\DateTimeBuilder.cs
- Common\SAIF.Common.Files\Core\Enums.cs
- Common\SAIF.Common.Files\Edi\IEdiEntity.cs
- Common\SAIF.Common.Files\Edi\Core\Builders\IDataElementBuilder.cs
- Common\SAIF.Common.Files\Edi\enums.cs
