Build lookup indexes
The model’s collections are flat arrays whose cross-references are plain
string ids (see IDs and references). For
anything beyond one-off lookups, build a Map index once — a single O(n)
pass that pays off on every subsequent lookup.
import { parseArchiModel } from '@cda/archi-semantic-core';
const model = parseArchiModel(xml);
const elementById = new Map(model.elements.map((e) => [e.id, e]));const relationshipById = new Map(model.relationships.map((r) => [r.id, r]));const folderById = new Map(model.folders.map((f) => [f.id, f]));const objectById = new Map(model.diagramObjects.map((o) => [o.id, o]));const profileById = new Map(model.profiles.map((p) => [p.id, p]));Resolving relationship endpoints
Section titled “Resolving relationship endpoints”A relationship’s source or target can be an element or another relationship (see Relationships), so resolve from both indexes:
function nodeName(id: string): string | null { return elementById.get(id)?.name ?? relationshipById.get(id)?.name ?? null;}Resolving the visual layer
Section titled “Resolving the visual layer”A connection’s sourceId/targetId point at diagram objects, not
semantic elements. Follow the chain:
function elementForObject(objectId: string) { const object = objectById.get(objectId); return object?.archimateElementId ? elementById.get(object.archimateElementId) : undefined;}View-local navigation
Section titled “View-local navigation”Views precompute their containment (see Views), so iterating a view’s diagram objects is direct:
function objectsInView(viewId: string) { const view = model.views.find((v) => v.id === viewId); if (!view) return []; return view.diagramObjectIds .map((id) => objectById.get(id)) .filter(Boolean);}When to skip indexes
Section titled “When to skip indexes”For a single traversal of one collection, find/filter are fine and
simpler. Build indexes when you will look things up repeatedly — typically
in any renderer, impact-analysis walk, or report generator.