---
title: SAIF.Presentation architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-08-17
library: SAIF.Presentation
reference_type: package
---

# SAIF.Presentation architecture

`SAIF.Presentation` is a small, single-purpose VB.NET class library whose entire compiled surface is `clsPreferences` and its `PrefScope` enumeration. It provides a scoped (application / page / web) in-memory user-preference store, backed by JSON-serialized persistence through the `SAIF.Framework.Preferences` package over an Oracle data layer. It is a leaf dependency consumed by `SAIF.Presentation.Web.Core.Infragistics111` and `SAIF.Presentation.Web.Controls.V2.Menu`.

## Responsibilities
- Load, in memory, every stored user-interface preference for a given user and application on construction (`clsPreferences.New` → `Initialize` → `Load`).
- Provide scoped read/write access to individual preference key/value pairs at application, page, or web scope (`PrefScope`), with a page-name override for non-web callers (`OverridePage`).
- Serialize the in-memory preference set to JSON and persist it through `SAIF.Framework.Preferences.PreferenceData.SavePreferences` (`Save()`), scoped to the current application.

## Component boundaries
- **Preference façade** (`clsPreferences`): the sole public type. It owns the loaded `Preference` records, exposes indexed lookup and mutators, and is the only caller of the framework preference service and the Oracle data layer.
- **Scope model** (`PrefScope`): a pure value type (`AppLevel`, `PageLevel`, `WebLevel`) with no behavior of its own; it parameterizes every lookup/mutator on `clsPreferences`.

This library has no controller, view, or data-access types of its own beyond the thin façade over the framework preference service — it is a presentation-support component, not a full MVC layer.

## Interaction model
- Every `clsPreferences` construction path (`Initialize`) opens `clsMSOracleDataLayer("CLM", …)` and immediately calls `PreferenceData.GetPreferencesForUser` to load the current user's stored preferences into memory.
- Callers (for example `SAIF.Presentation.Web.Core.Infragistics111`'s `m_controller.Model.Preferences`, and `SAIF.Presentation.Web.Controls.V2.Menu`'s `SAIFMenu`) read and mutate preferences purely in memory via `Item`, `Add`, `Remove`, `Clear`, `Delete`.
- `Save()` serializes each in-memory `Preference` whose `ApplicationName` matches the current application to JSON and calls `PreferenceData.SavePreferences` once per matching record; an empty preference-item dictionary is persisted as an empty string rather than skipped.

## Architecture diagram
The following diagram shows the preference load/save cycle around `clsPreferences`.

```mermaid
flowchart TD
	A["Caller (e.g. SAIF.Presentation.Web.Core.Infragistics111,<br>SAIF.Presentation.Web.Controls.V2.Menu)"] --> B["New clsPreferences(userID, application)"]
	B --> C["Initialize() -> Load()"]
	C --> D["clsMSOracleDataLayer('CLM', oracleDatabase)"]
	D --> E["PreferenceData.GetPreferencesForUser(userId)"]
	E --> F["In-memory Preference records"]
	A --> G["Item / Add / Remove / Clear / Delete"]
	G --> F
	A --> H["Save()"]
	H --> I["PreferenceData.SavePreferences(app, page, userId, json)"]
```

## Sequence diagram
The following diagram shows the primary construct/load/save sequence.

```mermaid
sequenceDiagram
	participant Caller
	participant Prefs as clsPreferences
	participant DAL as clsMSOracleDataLayer
	participant PrefData as PreferenceData
	Caller->>Prefs: New(userID, application)
	Prefs->>DAL: New("CLM", oracleDatabase)
	DAL-->>Prefs: IDataPortalInfo
	Prefs->>PrefData: GetPreferencesForUser(userId)
	PrefData-->>Prefs: Preference records
	Caller->>Prefs: Add(key, value, scope)
	Caller->>Prefs: Save()
	Prefs->>PrefData: SavePreferences(app, page, userId, json)
```

## Design constraints
- Every `clsPreferences` instance opens an Oracle connection on construction — there is no lazy loading or caching across instances, so preference-heavy pages construct a new connection per model.*
- The Oracle environment name is resolved via `AppGlobal.EnvironmentService.GetConfigSetting(EnvironmentConfigKeys.OracleDatabase)`† — no fallback exists if the environment service is unavailable or the key is unset.
- `Save()` always returns `False`, even on success, because the `result` local is never set to `True` before the (unreachable) trailing trace call — a verified defect in this library's source.
- No local business rules beyond preference scoping: only preferences whose `ApplicationName` matches the current application are persisted by `Save()`.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Database tables](database-tables.md)
- [SQL catalog](sql/index.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. Statements marked with ** could not be confirmed; treat as unknown until verified. Statements marked with † were retrieved from dependency library documentation via the Legends CLI RAG service. They describe inherited behavior from the indicated origin library and should be verified if the dependency version changes.

## Sources
- `SAIF.Presentation/clsPreferences.vb`
