using Invercargill.DataStructures; using InvercargillSql.Dialects; using InvercargillSql.Orm.Projections; namespace InvercargillSql.Orm { /** * Registry for entity mappers and projection definitions. * * TypeRegistry centralizes the registration and lookup of entity mappers * and projection definitions, allowing them to be shared across multiple * OrmSession instances if needed. * * Example usage: * {{{ * var registry = new TypeRegistry(); * registry.register_entity(user_mapper); * registry.register_projection(user_summary_definition); * * var session = new OrmSession(connection, dialect, registry); * }}} */ public class TypeRegistry : Object, TypeProvider { private Dictionary _mappers; private Dictionary _projection_registry; /** * Creates a new TypeRegistry instance. */ public TypeRegistry() { _mappers = new Dictionary(); _projection_registry = new Dictionary(); } /** * Registers an entity mapper for type T. * * @param mapper The entity mapper to register */ public void register_entity(EntityMapper mapper) { _mappers.set(typeof(T), mapper); } /** * Registers an entity mapper with schema introspection for type T. * * This method introspects the database schema to discover primary keys, * auto-increment columns, and other metadata. * * @param table_name The database table name * @param connection The database connection for schema introspection * @param dialect The SQL dialect for schema introspection * @param build_action A function that configures the EntityMapperBuilder * @throws SqlError if schema introspection fails */ public void register_with_schema( string table_name, Connection connection, SqlDialect dialect, owned GLib.Func> build_action ) throws SqlError { var builder = new EntityMapperBuilder(); builder.table(table_name); build_action(builder); // Introspect schema and apply to mapper var schema = dialect.introspect_schema(connection, table_name); var mapper = builder.build_with_schema(schema); _mappers.set(typeof(T), mapper); } /** * Registers an entity mapper by Type. * * This is a non-generic version for advanced scenarios. * * @param type The entity type * @param mapper The entity mapper to register */ public void register_entity_for_type(Type type, EntityMapper mapper) { _mappers.set(type, mapper); } /** * Gets the entity mapper for type T. * * @return The EntityMapper for type T * @throws SqlError if no mapper is registered for type T */ public EntityMapper get_mapper() throws SqlError { var mapper = _mappers.get_or_default(typeof(T)) as EntityMapper; if (mapper == null) { throw new SqlError.GENERAL_ERROR("Entity type not registered: " + typeof(T).name()); } return mapper; } /** * Gets the entity mapper for a type. * * This is a non-generic version that returns the base EntityMapper type. * * @param type The entity type to look up * @return The EntityMapper for the type, or null if not registered */ public EntityMapper? get_mapper_for_type(Type type) { return _mappers.get_or_default(type); } /** * Checks if an entity mapper is registered for type T. * * @return true if a mapper is registered, false otherwise */ public bool has_mapper() { return _mappers.has(typeof(T)); } /** * Checks if an entity mapper is registered for a type. * * @param type The entity type to check * @return true if a mapper is registered, false otherwise */ public bool has_mapper_for_type(Type type) { return _mappers.has(type); } /** * Registers a projection definition for type T. * * @param definition The projection definition to register */ public void register_projection(ProjectionDefinition definition) { _projection_registry.set(typeof(TProjection), definition); } /** * Registers a projection definition by Type. * * This is a non-generic version for advanced scenarios. * * @param type The projection type * @param definition The projection definition to register */ public void register_projection_for_type(Type type, ProjectionDefinition definition) { _projection_registry.set(type, definition); } /** * Gets the projection definition for type T. * * @return The ProjectionDefinition for the type, or null if not registered */ public ProjectionDefinition? get_projection() { return _projection_registry.get_or_default(typeof(TProjection)); } /** * Gets the projection definition by type. * * @param type The projection type to look up * @return The ProjectionDefinition for the type, or null if not registered */ public ProjectionDefinition? get_projection_for_type(Type type) { return _projection_registry.get_or_default(type); } /** * Checks if a projection is registered for type T. * * @return true if a projection is registered, false otherwise */ public bool has_projection() { return _projection_registry.has(typeof(T)); } /** * Checks if a projection is registered for a type. * * @param type The projection type to check * @return true if a projection is registered, false otherwise */ public bool has_projection_for_type(Type type) { return _projection_registry.has(type); } } }