# Architecture ## Module Overview ``` clotho-core Zero Spring dependency. All mapping, session, registry, and query logic. clotho-spring-boot-starter Spring Boot 3.x autoconfiguration. Thin layer: creates beans, bridges @Transactional, scans @ClothoRepository. Depends on clotho-core. clotho-dev-app Minimal Spring Boot application. Connected to a live ArcadeDB instance. Used throughout development for real-DB testing. Not a production artifact; not published. ``` --- ## clotho-core Component Map ``` ClothoSessionFactory (entry point) │ Holds: DriverRemoteConnection, TypeRegistry, global config │ ├── TypeRegistry │ Built once at startup from classpath scan. │ Maps: ArcadeDB label → Class │ Knows: Java + ArcadeDB inheritance hierarchy, additionalParents │ └── ClothoSession (unit of work, one per transaction/request) │ Holds: identity map (ARID → ClothoEntity instance) │ ├── load(Class, ARID) → T │ └── SubgraphLoader │ Uses: TypeRegistry, ObjectMapper │ Executes Gremlin traversal for root vertex + @Include boundary │ Cycle detection via visited-ARID set │ ├── save(entity) │ └── SubgraphPersistor │ Upserts root vertex/edge + all @Include elements recursively │ Uses ArcadeDB @version for optimistic locking │ @SubgraphType: iterates all ClothoEntity fields, saves each │ ├── delete(entity) │ Removes root vertex/edge from graph │ Does NOT cascade deletion to @Include elements │ └── query(Class, queryName, params) → List └── QueryExecutor Resolves named @Query, binds params, executes, maps results Also drives @ClothoRepository proxy methods ObjectMapper (used by SubgraphLoader and QueryExecutor) Gremlin Vertex/Edge → ClothoEntity subclass Always uses most-specific registered class (TypeRegistry lookup by label) Sets @Property fields, @OutVertex/@InVertex fields on edges SubgraphTypeAssembler (used by QueryExecutor for @SubgraphType returns) Maps Gremlin select() result map → @SubgraphType fields Binding: field name or @Alias → select key Each bound value is mapped via ObjectMapper ``` --- ## Data Flow: Loading a Composite Object ``` Developer: session.load(Order.class, arid) │ ▼ SubgraphLoader 1. g.V(arid.asString()) → TinkerPop Vertex (Order) 2. ObjectMapper.map(vertex) → Order instance (most-specific class) 3. Register in identity map 4. For each @Include field on Order: @Include @Via("HAS_LINE") List lines ┌──────────────────────────────────────────┐ │ g.V(arid).out("HAS_LINE") │ │ → [TinkerPop Vertex, Vertex, ...] │ │ for each: ObjectMapper.map(v) │ │ → OrderLine (or subtype by label) │ │ recurse: load OrderLine @Include fields│ └──────────────────────────────────────────┘ 5. Assemble Order.lines = [OrderLine, ...] 6. Return fully assembled Order ``` --- ## Data Flow: Saving a Composite Object ``` Developer: session.save(order) │ ▼ SubgraphPersistor 1. Upsert root Order vertex if order.getId() == null → create vertex with label "Order" else → update vertex, check @version (optimistic lock) 2. For each @Include field on Order: Field type is @VertexType (e.g., List): for each element → recursively save (SubgraphPersistor.save(orderLine)) ensure edge "HAS_LINE" exists from Order to OrderLine Field type is @EdgeType (e.g., List): save edge properties; ensure @OutVertex and @InVertex are already persisted 3. Identity map deduplication: elements already saved in this call are skipped 4. Removed elements: NOT deleted automatically ``` --- ## Data Flow: `@Query` on a `@ClothoRepository` ``` Developer: employeeQueries.findByDepartment("Engineering") │ ▼ ClothoRepository proxy (generated by QueryExecutor at startup) 1. Read @Query gremlin string from method annotation 2. Bind @Param values: replace :dept with "Engineering" 3. Execute: g.V().hasLabel('Employee').has('dept','Engineering') 4. For each result vertex: ObjectMapper.map(vertex) → most-specific Employee subclass 5. Return List ``` For `@SubgraphType` return: ``` 3. Execute query with select() → List of Maps 4. For each Map: SubgraphTypeAssembler.assemble(EmployeeProfile.class, map) → bind map keys to fields by name / @Alias → ObjectMapper.map() each value 5. Return List ``` --- ## Session Identity Map The identity map is the session's in-memory cache of loaded vertices and edges. - Key: `ARID` - Value: `ClothoEntity` instance Rules: - First load of an ARID → fetch from DB, map to Java, store in map, return - Subsequent load of same ARID → return existing instance (no DB call) - `save()` does NOT clear the identity map; the instance is mutated in place - `close()` clears the map and releases the Gremlin connection The map operates at the individual vertex/edge level. Multiple composite objects (e.g., an `Order` and an `EmployeeProfile`) may both hold references to the same `Address` instance if their traversals reached the same ARID. --- ## TypeRegistry Startup Validation At `ClothoSessionFactory.build()` time, the TypeRegistry validates: - Every `@VertexType` class extends `ClothoVertex` - Every `@EdgeType` class extends `ClothoEdge` - No two classes claim the same label - `additionalParents` labels are resolvable to registered classes - `parentLabel` values are resolvable to registered classes - Every `@Include` field is paired with `@Via` - `@OutVertex` / `@InVertex` field types are `@VertexType` classes Startup failure with a descriptive message is strongly preferred over silent misconfiguration that produces confusing runtime errors. --- ## Package Structure ``` com.binarygolem.clotho .model ClothoEntity ClothoVertex ClothoEdge ARID UnknownTypeBehavior .annotation VertexType EdgeType SubgraphType RID Property Include Via Direction OutVertex InVertex Alias Query Queries (container for @Repeatable @Query) Param ClothoRepository .session ClothoSession ClothoSessionFactory ClothoSessionFactoryBuilder .registry TypeRegistry TypeRegistryBuilder TypeDescriptor (holds metadata for one registered type) .mapping ObjectMapper SubgraphLoader SubgraphPersistor SubgraphTypeAssembler .query QueryExecutor QueryDescriptor (holds parsed @Query metadata for one method) ParameterBinder .exception ClothoException UnknownTypeException OptimisticLockException ClothoConfigurationException // clotho-spring-boot-starter com.binarygolem.clotho.spring .config ClothoAutoConfiguration ClothoProperties .tx ClothoTransactionManager ClothoTransactionObject .repository ClothoRepositoryScanner ClothoRepositoryProxyFactory ```