Graph Editor
============

.. rubric:: Files: 5 | Namespace: Graph | Pattern: Recommended (multiple attachments, function pools)

Graph topology editor demonstrating best practices.

----

Graph.dsm
---------

**Domain:** Graph, Vertex, Edge

This file defines the core data model for a graph editor application. It demonstrates the
**recommended Viper pattern** with multiple attachments per concept, separating concerns
cleanly.

Data Model Design
^^^^^^^^^^^^^^^^^

- **Three concepts** (Graph, Vertex, Edge) represent the topological entities
- **Attachments separate concerns**: topology (structure), selection (UI state),
  description (metadata), render2DAttributes (visualization), visualAttributes (appearance)
- **Key insight**: A Vertex can exist without render attributes (topology-only) or without
  visual attributes (invisible vertex). Each attachment is optional and independent.

Why Multiple Attachments Matter
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- ``topology`` attachment stores which vertices/edges exist in the graph
- ``selection`` attachment tracks UI selection state separately from topology
- ``visualAttributes`` and ``render2DAttributes`` handle rendering independently
- Adding a new concern (e.g., ``physicsAttributes``) requires zero migration - just add a
  new attachment

This is the **anti-monolithic pattern**: instead of one giant ``VertexProperties`` struct,
each concern lives in its own attachment.

.. code-block:: dsm

   // Types definitions
   namespace Graph {27c49329-a399-415c-baf0-db42949d2ba2} {

   """A graph."""
   concept Graph;

   """A vertex in a graph."""
   concept Vertex;

   """An edge in a graph."""
   concept Edge;

   """The selected vertices and edges."""
   struct GraphSelection {
       set<key<Vertex>> vertexKeys;
       set<key<Edge>> edgeKeys;
   };

   """An edge in the graph topology."""
   struct EdgeTopology {
       key<Vertex> vaKey;
       key<Vertex> vbKey;
   };

   """The vertices and edges of the graph topology."""
   struct GraphTopology {
       set<key<Vertex>> vertexKeys;
       set<key<Edge>> edgeKeys;
   };

   """A Rectangle."""
   struct Rectangle {
       """the x origin."""
       float x;
       """the y origin."""
       float y;
       """the width."""
       float w;
       """the height."""
       float h;
   };

   """The descriptive information."""
   struct GraphDescription {
       string name;
       string author;
       string createDate;
   };

   """A Position."""
   struct Position {
       float x;
       float y;
   };

   """The attributes used to render a topological vertex in 2D."""
   struct Vertex2DAttributes {
       Position position;
   };

   """An RGB Color."""
   struct Color {
       float red;
       float green;
       float blue;
   };

   """The visual attributes of a vertex."""
   struct VertexVisualAttributes {
       int64 value;
       Color color;
   };

   };

   // Attachments definitions
   namespace Graph {27c49329-a399-415c-baf0-db42949d2ba2} {
   """The topology of a graph."""
   attachment<Graph, GraphTopology> topology;

   """A collection of tags for a graph."""
   attachment<Graph, map<string, string>> tags;

   """A collection of comments for a Graph."""
   attachment<Graph, xarray<string>> comments;

   """The selected vertices of a graph."""
   attachment<Graph, GraphSelection> selection;

   """The descriptive information of a graph."""
   attachment<Graph, GraphDescription> description;

   """The render attributes used to render a vertex of a graph in 2D."""
   attachment<Vertex, Vertex2DAttributes> render2DAttributes;

   """The visual attributes used to render a vertex of a graph."""
   attachment<Vertex, VertexVisualAttributes> visualAttributes;

   """An Edge in the graph topology."""
   attachment<Edge, EdgeTopology> topology;

   };

----

Pool_ModelGraph.dsm
-------------------

**Domain:** Pool: ModelGraph

This is an **attachment_function_pool** - functions that modify the AttachmentMutableState.

Function Categories
^^^^^^^^^^^^^^^^^^^

- **Topology operations**: ``newVertex``, ``newEdge``, ``clearGraph`` - basic graph manipulation
- **Property setters**: ``setVertexColor``, ``setVertexPosition``, ``setVertexValue`` - modify
  vertex attachments
- **Batch operations**: ``moveVertices``, ``randomGraph`` - operate on multiple elements
- **Metadata**: ``setGraphLabel``, ``setGraphTag``, ``appendGraphComment`` - graph-level
  annotations
- **XArray operations**: ``insertGraphComment``, ``removeGraphComment``,
  ``updateGraphComment`` - demonstrate ordered collection with UUID-based positions (not
  indices)

Testing/Demo Functions
^^^^^^^^^^^^^^^^^^^^^^

These functions are intentionally broken for demonstrations:

- ``graphWithError`` - throws during commit to test error handling
- ``graphWithMissingVertex`` - creates dangling edge references
- ``deleteSelectionBugged`` - deletes vertices without cleaning edges
- ``killer`` - stress test that creates many mutations

.. note::

   All ``mutable`` functions operate within a mutation context (AttachmentMutating).
   Non-mutable functions (queries) only need a reading context (AttachmentGetting).

.. code-block:: dsm

   """This pool provides access to functions used to edit the graph topology."""
   attachment_function_pool ModelGraph {9bdcbb5b-76e9-426f-b8a6-a10ed2d949e6} {

   """Append a new comment."""
   mutable void appendGraphComment(key<Graph> graphKey, string comment);

   """Clear the graph."""
   mutable void clearGraph(key<Graph> graphKey);

   """Delete a vertex without deleting connected edges."""
   mutable void deleteSelectionBugged(key<Graph> graphKey);

   """Throw an error while creating a graph."""
   mutable void graphWithError(key<Graph> graphKey);

   """Create a graph with missing vertices to illustrate graph integrity."""
   mutable void graphWithMissingVertex(key<Graph> graphKey);

   """Create a graph with missing vertex property to illustrate graph integrity."""
   mutable void graphWithMissingVertexProperties(key<Graph> graphKey);

   """Insert a new comment at a specific xarray position (not an index)."""
   mutable void insertGraphComment(key<Graph> graphKey, uuid position, string comment);

   """Create mutations that destroy the usability of the Commit."""
   mutable void killer(key<Graph> graphKey, uint64 vertexCount);

   """Move the vertices by the offset."""
   mutable void moveVertices(set<key<Vertex>> vertexKeys, Position offset);

   """Create a new edge."""
   mutable key<Edge> newEdge(key<Graph> graphKey, key<Vertex> vaKey, key<Vertex> vbKey);

   """Create a vertex with the specified attributes."""
   mutable key<Vertex> newVertex(key<Graph> graphKey, int64 value, Position position);

   """Append a random comment."""
   mutable void randomComment(key<Graph> graphKey);

   """Create a random edge or raise if the graph is complete."""
   mutable key<Edge> randomEdge(key<Graph> graphKey);

   """Create a new random graph in rect."""
   mutable void randomGraph(key<Graph> graphKey, uint64 vertexCount, uint64 edgeCount, Rectangle rect);

   """Insert a new random tag."""
   mutable void randomTag(key<Graph> graphKey);

   """Create a random vertex."""
   mutable key<Vertex> randomVertex(key<Graph> graphKey, Rectangle rect);

   """Remove a comment at a specific xarray position (not an index)."""
   mutable void removeGraphComment(key<Graph> graphKey, uuid position);

   """Set the label of the graph description."""
   mutable void setGraphLabel(key<Graph> graphKey, string label);

   """Replace or insert the tag."""
   mutable void setGraphTag(key<Graph> graphKey, string key, string value);

   """Set the vertex color."""
   mutable void setVertexColor(key<Vertex> vertexKey, Color color);

   """Set the vertex position."""
   mutable void setVertexPosition(key<Vertex> vertexKey, Position position);

   """Set the vertex value."""
   mutable void setVertexValue(key<Vertex> vertexKey, int64 value);

   """Remove the tag."""
   mutable void unsetGraphTags(key<Graph> graphKey, set<string> keys);

   """Update the comment at a specific xarray position (not an index)."""
   mutable void updateGraphComment(key<Graph> graphKey, uuid position, string comment);

   """Update a tag."""
   mutable void updateGraphTag(key<Graph> graphKey, string key, string value);

   """Test no args."""
   mutable void noArgs();

   };

----

Pool_ModelIntegrity.dsm
-----------------------

**Domain:** Pool: ModelIntegrity

This pool demonstrates **referential integrity repair** - what happens when the graph has
dangling references (edges pointing to deleted vertices).

Three Repair Strategies
^^^^^^^^^^^^^^^^^^^^^^^

- ``restoreIntegrityByCreating`` - recreate missing vertices (preserve topology)
- ``restoreIntegrityByDeleting`` - remove edges with dangling references (preserve
  consistency)
- ``restoreIntegrityByRestoring`` - respawn deleted elements from history

Why This Matters
^^^^^^^^^^^^^^^^

In Viper, concepts (Vertex, Edge) are identified by keys. If you
delete a Vertex without updating Edge references, edges become "orphaned". This pool shows
how to detect and repair such inconsistencies.

**Use case**: After running ``deleteSelectionBugged`` from ModelGraph pool (which
intentionally creates orphans), use these functions to restore graph integrity.

.. code-block:: dsm

   """This pool provides access functions used to restore the integrity of the graph."""
   attachment_function_pool ModelIntegrity {95e0f859-65e0-419e-8b81-77547c73b759} {

   """Restore the graph integrity by creating missing elements."""
   mutable void restoreIntegrityByCreating(key<Graph> graphKey);

   """Restore the graph integrity by removing elements."""
   mutable void restoreIntegrityByDeleting(key<Graph> graphKey);

   """Restore the graph integrity by respawning elements."""
   mutable void restoreIntegrityByRestoring(key<Graph> graphKey);

   """Restore attributes of the selected vertices."""
   mutable void restoreVertexSelection(key<Graph> graphKey);

   };

----

Pool_ModelSelection.dsm
-----------------------

**Domain:** Pool: ModelSelection

This pool manages **UI selection state** - which vertices and edges are currently selected
by the user. Selection is stored in the ``Graph.selection`` attachment, separate from
topology.

Selection Operations
^^^^^^^^^^^^^^^^^^^^

- **Set operations**: ``selectAll``, ``deselectAll``, ``invertSelection`` - bulk selection
  changes
- **Element-specific**: ``setSelectionToVertex``, ``setSelectionToEdge`` - single element
  selection
- **Combine mode**: ``combineSelectionWithVertex/Edge`` - add/remove from current
  selection (shift-click behavior)
- **Queries**: ``selectedVertices``, ``selectedEdges`` - return current selection (non-mutable)

.. note::

   ``deleteSelection`` operates on selection then modifies topology -
   demonstrating how UI state drives data mutations.

.. code-block:: dsm

   """This pool provides access to functions used to edit the selection."""
   attachment_function_pool ModelSelection {5318ad8d-79d8-498e-b080-eccf15e4a74d} {

   """Combine the edge-selected state with the edge selection."""
   mutable void combineSelectionWithEdge(key<Graph> graphKey, key<Edge> edgeKey, bool selected);

   """Combine the vertex-selected state with the vertex selection."""
   mutable void combineSelectionWithVertex(key<Graph> graphKey, key<Vertex> vertexKey, bool selected);

   """Delete the selected elements."""
   mutable void deleteSelection(key<Graph> graphKey);

   """Deselect all edges and vertices."""
   mutable void deselectAll(key<Graph> graphKey);

   """Deselect all edges."""
   mutable void deselectAllEdges(key<Graph> graphKey);

   """Deselect all vertices."""
   mutable void deselectAllVertices(key<Graph> graphKey);

   """Increment the value of selected vertices."""
   mutable void incrementVertexValue(key<Graph> graphKey, int64 value);

   """Invert the edge selection."""
   mutable void invertEdgesSelection(key<Graph> graphKey);

   """Invert the selection for edges and vertices."""
   mutable void invertSelection(key<Graph> graphKey);

   """Invert the vertex selection."""
   mutable void invertVerticesSelection(key<Graph> graphKey);

   """Select all edges and vertices."""
   mutable void selectAll(key<Graph> graphKey);

   """Select all edges."""
   mutable void selectAllEdges(key<Graph> graphKey);

   """Select all vertices."""
   mutable void selectAllVertices(key<Graph> graphKey);

   """Return selected edges."""
   set<key<Edge>> selectedEdges(key<Graph> graphKey);

   """Return selected vertices."""
   set<key<Vertex>> selectedVertices(key<Graph> graphKey);

   """Reduce the selection to the specified edges and vertices."""
   mutable void setSelection(key<Graph> graphKey, set<key<Vertex>> vertexKeys, set<key<Edge>> edgeKeys);

   """Reduce the edge selection to the edge."""
   mutable void setSelectionToEdge(key<Graph> graphKey, key<Edge> edgeKey);

   """Reduce the selection to the vertex."""
   mutable void setSelectionToVertex(key<Graph> graphKey, key<Vertex> vertexKey);

   };

----

Pool_Tools.dsm
--------------

**Domain:** Pool: Tools

This is a **function_pool** (not attachment_function_pool) - pure utility

Difference from attachment_function_pool
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- ``function_pool``: Pure functions
- ``attachment_function_pool``: Functions that modify the AttachmentMutableState

Utility Functions
^^^^^^^^^^^^^^^^^

- ``add``, ``isEven``, ``isGreater`` - basic arithmetic/comparison (demonstration purposes)
- ``randomWord`` - generate random strings for testing

**Use case**: These functions are stateless and available in RPC context for client-side
computations or test data generation (no AttachmentMutating context required).

.. code-block:: dsm

   """This pool provides access to the various utility functions."""
   function_pool Tools {dc9740c9-9d1d-4c1e-9caa-4c8843b91e82} {

   """Return a + b."""
   int64 add(int64 a, int64 b);

   """Return true if a is even."""
   bool isEven(int64 a);

   """Return true if a > b."""
   bool isGreater(any a, any b);

   """Return a random word."""
   string randomWord(uint64 size);

   };
