modules-forms-vtables.md 4.06 KB

Modules, forms, virtual tables

The three core nouns of xly's metadata model. A reader who internalises these can navigate the rest of the framework. The vocabulary is not always consistent in the codebase — same concept, different names in different files — so part of this page is reconciling the synonyms.

Module

The unit of "a configurable thing in the system".

  • One row per module in gdsmodule.
  • Carries the URL fragment (sName), display names (sChinese, sEnglish, sBig5), tree position (sParentId, sAllId), product edition (sVersionFlowId, see Slice 2), optional CRUD procedure names (sSaveProName, sDeleteProName, sProcName, sCalcProName, sSaveProNameBefore).

The Java codebase calls this concept "module", "model", "models", and "modle" (typo, common). The variable sModelsId and method getModelConfigByModleId both take a module sId, despite the naming. See the naming caution in Slice 1.

Form

The screen layout for a module — header + N field definitions.

  • Master: one row per form in gdsconfigformmaster. Carries the backing object (sTbName), backing-object type (sType{table, view, proc}), default SQL fragments (sSqlStr, sWhere, sOrder), grid behaviour (bGrd, iPageSize), jurisdiction column.
  • Slave: one row per field in gdsconfigformslave. Carries the field name (sName — matches a column in the backing object), control type (sControlName), display labels, validation rules, default value, dropdown SQL, button instructions.
  • A module is linked to its form via gdsconfigformmaster.sParentId = gdsmodule.sId — semantic FK, no enforcement. (Note: gdsmodule.sFormId exists but is empty for most modules and is not the canonical link.)

The form is the user-visible artefact: when a PM "creates a screen" in BACK, what they're really doing is INSERTing a gdsconfigformmaster row plus 5-50 gdsconfigformslave rows.

Virtual table

xly's term (and table prefix) for a "table" that is itself defined as metadata, not as a CREATE TABLE statement.

Virtual tables are how PMs declare "I want this kind of thing" without asking an engineer. Most virtual tables back to a real physical table (the framework supports the migration step, or it pre-creates a generic "wide" table the PM populates), but the abstraction the runtime sees is the metadata declaration, not the underlying storage.

This is distinct from a database view: a virtual table is metadata; a view is a CREATE VIEW SQL object. Both can back a form (via gdsconfigformmaster.sType = 'table' or 'view'). See Slice 3 for the view-backed case.

How they fit together

gdsmodule  (module, 1 row)
   └── (joined via sParentId)
       gdsconfigformmaster  (form-master, 1 row per form)
          ├── gdsconfigformslave  (fields, N rows)
          ├── gdsconfigformcustomslave  (per-tenant fields, N or 0)
          └── gdsconfigformuserslave    (per-user tweaks, N or 0)

gdsmodule.sName   →  registered route in  gdsroute  (URL whitelist)
gdsmodule.sFormId →  (mostly empty — historical)

Every form has exactly one module. Every module should have at most one form, but a few have several gdsconfigformmaster rows pointing at the same sParentId — those represent screens with multiple panels or sub-tabs.

Three nouns, one engine

The runtime — BusinessBaseController and BusinessBaseServiceImpl, documented in Slice 1 — knows how to render any module / form / virtual-table combination. There is no per-module Java code. PMs creating new modules are creating new rows; they are not creating new code paths.