Class JsonFileAnnotationLayer

Namespace
Kuestenlogik.Bowire.Semantics
Assembly
Kuestenlogik.Bowire.dll

File-backed annotation layer. Loads and persists a single bowire.schema-hints.json file (project or user scope — same format) and exposes the parsed entries via the same AnnotationKey / SemanticTag surface as InMemoryAnnotationLayer.

public sealed class JsonFileAnnotationLayer : IDisposable
Inheritance
JsonFileAnnotationLayer
Implements
Inherited Members

Remarks

Reads are cached in-memory after the first LoadAsync(CancellationToken); subsequent Entries reads hit the cache. Writes (SaveAsync(CancellationToken)) go through a write-to-temp-then-rename sequence so a concurrent reader never sees a half-written file — the same atomic-replacement pattern the rest of Bowire's disk-sync layers use.

Concurrency: a per-instance SemaphoreSlim serialises writes against one another. Two JsonFileAnnotationLayer instances writing to the same file path defend against corruption via the atomic rename — the last writer wins the file, intermediate states are never observable on disk.

Constructors

JsonFileAnnotationLayer(string)

Construct a layer pointing at filePath. The file does not have to exist — a missing file is treated as an empty layer and is only written on the first SaveAsync(CancellationToken).

public JsonFileAnnotationLayer(string filePath)

Parameters

filePath string

Properties

Count

Number of entries currently cached.

public int Count { get; }

Property Value

int

Entries

Snapshot of every cached entry.

public IReadOnlyCollection<KeyValuePair<AnnotationKey, SemanticTag>> Entries { get; }

Property Value

IReadOnlyCollection<KeyValuePair<AnnotationKey, SemanticTag>>

FilePath

Absolute or relative path the layer reads from / writes to.

public string FilePath { get; }

Property Value

string

IsLoaded

True after LoadAsync(CancellationToken) has completed at least once.

public bool IsLoaded { get; }

Property Value

bool

Methods

Dispose()

public void Dispose()

Get(AnnotationKey)

Get the raw tag at key (no priority resolution).

public SemanticTag? Get(AnnotationKey key)

Parameters

key AnnotationKey

Returns

SemanticTag

LoadAsync(CancellationToken)

Load (or reload) the file into the in-memory cache. Idempotent: reload clears the cache before re-parsing. A missing file resets the cache to empty and is not an error — that is the "nothing persisted yet" steady state.

public Task LoadAsync(CancellationToken ct = default)

Parameters

ct CancellationToken

Returns

Task

Remove(AnnotationKey)

Remove the entry at key. Returns true when an entry was actually removed. Touches only the in-memory cache; call SaveAsync(CancellationToken) to persist the deletion.

public bool Remove(AnnotationKey key)

Parameters

key AnnotationKey

Returns

bool

Replace(IEnumerable<KeyValuePair<AnnotationKey, SemanticTag>>)

Replace the cache content with entries. Does not touch disk; call SaveAsync(CancellationToken) separately to persist. Use this to push a freshly-edited set of annotations into the layer before saving.

public void Replace(IEnumerable<KeyValuePair<AnnotationKey, SemanticTag>> entries)

Parameters

entries IEnumerable<KeyValuePair<AnnotationKey, SemanticTag>>

SaveAsync(CancellationToken)

Persist the current cache to FilePath. Writes go through a FilePath + ".tmp" file that is then atomically renamed over the destination, so concurrent readers never see a half-written document. Parent directories are created on demand.

public Task SaveAsync(CancellationToken ct = default)

Parameters

ct CancellationToken

Returns

Task

Set(AnnotationKey, SemanticTag)

Insert or replace the tag at key. Touches only the in-memory cache; call SaveAsync(CancellationToken) to persist.

public JsonFileAnnotationLayer Set(AnnotationKey key, SemanticTag tag)

Parameters

key AnnotationKey
tag SemanticTag

Returns

JsonFileAnnotationLayer

Remarks

Phase 4 — the right-click UI's "Persist for user / project" path lands here. The session-tier layer uses Set(AnnotationKey, SemanticTag) directly; this method is the file-tier mirror so all three tiers share a single write surface from the caller's perspective.