type-registry.vala 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. using Invercargill.DataStructures;
  2. using InvercargillSql.Dialects;
  3. using InvercargillSql.Orm.Projections;
  4. namespace InvercargillSql.Orm {
  5. /**
  6. * Registry for entity mappers and projection definitions.
  7. *
  8. * TypeRegistry centralizes the registration and lookup of entity mappers
  9. * and projection definitions, allowing them to be shared across multiple
  10. * OrmSession instances if needed.
  11. *
  12. * Example usage:
  13. * {{{
  14. * var registry = new TypeRegistry();
  15. * registry.register_entity<User>(user_mapper);
  16. * registry.register_projection<UserSummary>(user_summary_definition);
  17. *
  18. * var session = new OrmSession(connection, dialect, registry);
  19. * }}}
  20. */
  21. public class TypeRegistry : Object, TypeProvider {
  22. private Dictionary<Type, EntityMapper> _mappers;
  23. private Dictionary<Type, ProjectionDefinition> _projection_registry;
  24. /**
  25. * Creates a new TypeRegistry instance.
  26. */
  27. public TypeRegistry() {
  28. _mappers = new Dictionary<Type, EntityMapper>();
  29. _projection_registry = new Dictionary<Type, ProjectionDefinition>();
  30. }
  31. /**
  32. * Registers an entity mapper for type T.
  33. *
  34. * @param mapper The entity mapper to register
  35. */
  36. public void register_entity<T>(EntityMapper<T> mapper) {
  37. _mappers.set(typeof(T), mapper);
  38. }
  39. /**
  40. * Registers an entity mapper with schema introspection for type T.
  41. *
  42. * This method introspects the database schema to discover primary keys,
  43. * auto-increment columns, and other metadata.
  44. *
  45. * @param table_name The database table name
  46. * @param connection The database connection for schema introspection
  47. * @param dialect The SQL dialect for schema introspection
  48. * @param build_action A function that configures the EntityMapperBuilder
  49. * @throws SqlError if schema introspection fails
  50. */
  51. public void register_with_schema<T>(
  52. string table_name,
  53. Connection connection,
  54. SqlDialect dialect,
  55. owned GLib.Func<EntityMapperBuilder<T>> build_action
  56. ) throws SqlError {
  57. var builder = new EntityMapperBuilder<T>();
  58. builder.table(table_name);
  59. build_action(builder);
  60. // Introspect schema and apply to mapper
  61. var schema = dialect.introspect_schema(connection, table_name);
  62. var mapper = builder.build_with_schema(schema);
  63. _mappers.set(typeof(T), mapper);
  64. }
  65. /**
  66. * Registers an entity mapper by Type.
  67. *
  68. * This is a non-generic version for advanced scenarios.
  69. *
  70. * @param type The entity type
  71. * @param mapper The entity mapper to register
  72. */
  73. public void register_entity_for_type(Type type, EntityMapper mapper) {
  74. _mappers.set(type, mapper);
  75. }
  76. /**
  77. * Gets the entity mapper for type T.
  78. *
  79. * @return The EntityMapper<T> for type T
  80. * @throws SqlError if no mapper is registered for type T
  81. */
  82. public EntityMapper<T> get_mapper<T>() throws SqlError {
  83. var mapper = _mappers.get_or_default(typeof(T)) as EntityMapper<T>;
  84. if (mapper == null) {
  85. throw new SqlError.GENERAL_ERROR("Entity type not registered: " + typeof(T).name());
  86. }
  87. return mapper;
  88. }
  89. /**
  90. * Gets the entity mapper for a type.
  91. *
  92. * This is a non-generic version that returns the base EntityMapper type.
  93. *
  94. * @param type The entity type to look up
  95. * @return The EntityMapper for the type, or null if not registered
  96. */
  97. public EntityMapper? get_mapper_for_type(Type type) {
  98. return _mappers.get_or_default(type);
  99. }
  100. /**
  101. * Checks if an entity mapper is registered for type T.
  102. *
  103. * @return true if a mapper is registered, false otherwise
  104. */
  105. public bool has_mapper<T>() {
  106. return _mappers.has(typeof(T));
  107. }
  108. /**
  109. * Checks if an entity mapper is registered for a type.
  110. *
  111. * @param type The entity type to check
  112. * @return true if a mapper is registered, false otherwise
  113. */
  114. public bool has_mapper_for_type(Type type) {
  115. return _mappers.has(type);
  116. }
  117. /**
  118. * Registers a projection definition for type T.
  119. *
  120. * @param definition The projection definition to register
  121. */
  122. public void register_projection<TProjection>(ProjectionDefinition definition) {
  123. _projection_registry.set(typeof(TProjection), definition);
  124. }
  125. /**
  126. * Registers a projection definition by Type.
  127. *
  128. * This is a non-generic version for advanced scenarios.
  129. *
  130. * @param type The projection type
  131. * @param definition The projection definition to register
  132. */
  133. public void register_projection_for_type(Type type, ProjectionDefinition definition) {
  134. _projection_registry.set(type, definition);
  135. }
  136. /**
  137. * Gets the projection definition for type T.
  138. *
  139. * @return The ProjectionDefinition for the type, or null if not registered
  140. */
  141. public ProjectionDefinition? get_projection<TProjection>() {
  142. return _projection_registry.get_or_default(typeof(TProjection));
  143. }
  144. /**
  145. * Gets the projection definition by type.
  146. *
  147. * @param type The projection type to look up
  148. * @return The ProjectionDefinition for the type, or null if not registered
  149. */
  150. public ProjectionDefinition? get_projection_for_type(Type type) {
  151. return _projection_registry.get_or_default(type);
  152. }
  153. /**
  154. * Checks if a projection is registered for type T.
  155. *
  156. * @return true if a projection is registered, false otherwise
  157. */
  158. public bool has_projection<T>() {
  159. return _projection_registry.has(typeof(T));
  160. }
  161. /**
  162. * Checks if a projection is registered for a type.
  163. *
  164. * @param type The projection type to check
  165. * @return true if a projection is registered, false otherwise
  166. */
  167. public bool has_projection_for_type(Type type) {
  168. return _projection_registry.has(type);
  169. }
  170. }
  171. }