using ZB.MOM.WW.CBDD.Bson; using ZB.MOM.WW.CBDD.Core.Collections; using ZB.MOM.WW.CBDD.Core.Metadata; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace ZB.MOM.WW.CBDD.Shared { // --- Basic Entities --- public class User { public ObjectId Id { get; set; } public string Name { get; set; } = ""; public int Age { get; set; } } // --- Complex Entities (Nested) --- public class ComplexUser { [BsonId] public ObjectId Id { get; set; } public string Name { get; set; } = ""; // Direct nested object public Address MainAddress { get; set; } = new(); // Collection of nested objects public List
OtherAddresses { get; set; } = new(); // Primitive collection public List Tags { get; set; } = new(); [BsonIgnore] public string Secret { get; set; } = ""; } public class Address { public string Street { get; set; } = ""; public City City { get; set; } = new(); // Depth 2 } public class City { public string Name { get; set; } = ""; public string ZipCode { get; set; } = ""; } // --- Primary Key Test Entities --- public class IntEntity { public int Id { get; set; } public string? Name { get; set; } } public class StringEntity { public required string Id { get; set; } public string? Value { get; set; } } public class GuidEntity { public Guid Id { get; set; } public string? Name { get; set; } } /// /// Entity with string key NOT named "Id" - tests custom key name support /// public class CustomKeyEntity { [System.ComponentModel.DataAnnotations.Key] public required string Code { get; set; } public string? Description { get; set; } } // --- Multi-collection / Auto-init entities --- public class AutoInitEntity { public int Id { get; set; } public string Name { get; set; } = string.Empty; } public class Person { public int Id { get; set; } public string Name { get; set; } = ""; public int Age { get; set; } } public class Product { public int Id { get; set; } public string Title { get; set; } = ""; public decimal Price { get; set; } } public class AsyncDoc { public int Id { get; set; } public string Name { get; set; } = ""; } public class SchemaUser { public int Id { get; set; } public string Name { get; set; } = ""; public Address Address { get; set; } = new(); } public class VectorEntity { public ObjectId Id { get; set; } public string Title { get; set; } = ""; public float[] Embedding { get; set; } = Array.Empty(); } public class GeoEntity { public ObjectId Id { get; set; } public string Name { get; set; } = ""; public (double Latitude, double Longitude) Location { get; set; } } public record OrderId(string Value) { public OrderId() : this(string.Empty) { } } public class OrderIdConverter : ValueConverter { public override string ConvertToProvider(OrderId model) => model?.Value ?? string.Empty; public override OrderId ConvertFromProvider(string provider) => new OrderId(provider); } public class Order { public OrderId Id { get; set; } = null!; public string CustomerName { get; set; } = ""; } public class TestDocument { public ObjectId Id { get; set; } public string Category { get; set; } = string.Empty; public int Amount { get; set; } public string Name { get; set; } = string.Empty; } public class OrderDocument { public ObjectId Id { get; set; } public string ItemName { get; set; } = string.Empty; public int Quantity { get; set; } } public class OrderItem { public string Name { get; set; } = string.Empty; public int Price { get; set; } } public class ComplexDocument { public ObjectId Id { get; set; } public string Title { get; set; } = string.Empty; public Address ShippingAddress { get; set; } = new(); public List Items { get; set; } = new(); } [Table("custom_users", Schema = "test")] public class AnnotatedUser { [Key] public ObjectId Id { get; set; } [Required] [Column("display_name")] [StringLength(50, MinimumLength = 3)] public string Name { get; set; } = ""; [Range(0, 150)] public int Age { get; set; } [NotMapped] public string ComputedInfo => $"{Name} ({Age})"; [Column(TypeName = "geopoint")] public (double Lat, double Lon) Location { get; set; } } public class PersonV2 { public ObjectId Id { get; set; } public string Name { get; set; } = string.Empty; public int Age { get; set; } } /// /// Entity used to test DbContext inheritance /// public class ExtendedEntity { public int Id { get; set; } public string Description { get; set; } = string.Empty; public DateTime CreatedAt { get; set; } } // ===== SOURCE GENERATOR FEATURE TESTS ===== /// /// Base entity with Id property - test inheritance /// public class BaseEntityWithId { public ObjectId Id { get; set; } public DateTime CreatedAt { get; set; } } /// /// Derived entity that inherits Id from base class /// public class DerivedEntity : BaseEntityWithId { public string Name { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; } /// /// Entity with computed getter-only properties (should be excluded from serialization) /// public class EntityWithComputedProperties { public ObjectId Id { get; set; } public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public int BirthYear { get; set; } // Computed properties - should NOT be serialized public string FullName => $"{FirstName} {LastName}"; public int Age => DateTime.Now.Year - BirthYear; public string DisplayInfo => $"{FullName} (Age: {Age})"; } /// /// Entity with advanced collection types (HashSet, ISet, LinkedList, etc.) /// public class EntityWithAdvancedCollections { public ObjectId Id { get; set; } public string Name { get; set; } = string.Empty; // Various collection types that should all be recognized public HashSet Tags { get; set; } = new(); public ISet Numbers { get; set; } = new HashSet(); public LinkedList History { get; set; } = new(); public Queue PendingItems { get; set; } = new(); public Stack UndoStack { get; set; } = new(); // Nested objects in collections public HashSet
Addresses { get; set; } = new(); public ISet FavoriteCities { get; set; } = new HashSet(); } /// /// Entity with private setters (requires reflection-based deserialization) /// public class EntityWithPrivateSetters { public ObjectId Id { get; private set; } public string Name { get; private set; } = string.Empty; public int Age { get; private set; } public DateTime CreatedAt { get; private set; } // Factory method for creation public static EntityWithPrivateSetters Create(string name, int age) { return new EntityWithPrivateSetters { Id = ObjectId.NewObjectId(), Name = name, Age = age, CreatedAt = DateTime.UtcNow }; } } /// /// Entity with init-only setters (can use object initializer) /// public class EntityWithInitSetters { public ObjectId Id { get; init; } public required string Name { get; init; } public int Age { get; init; } public DateTime CreatedAt { get; init; } } // ======================================== // Circular Reference Test Entities // ======================================== /// /// Employee with self-referencing via ObjectIds (organizational hierarchy) /// Tests: self-reference using referencing (BEST PRACTICE) /// Recommended: Avoids embedding which can lead to large/circular documents /// public class Employee { public ObjectId Id { get; set; } public string Name { get; set; } = string.Empty; public string Department { get; set; } = string.Empty; public ObjectId? ManagerId { get; set; } // Reference to manager public List? DirectReportIds { get; set; } // References to direct reports (best practice) } /// /// Category with referenced products (N-N using ObjectId references) /// Tests: N-N relationships using referencing (BEST PRACTICE for document databases) /// Recommended: Avoids large documents, better for queries and updates /// public class CategoryRef { public ObjectId Id { get; set; } public string Name { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; public List? ProductIds { get; set; } // Only IDs - no embedding } /// /// Product with referenced categories (N-N using ObjectId references) /// Tests: N-N relationships using referencing (BEST PRACTICE for document databases) /// Recommended: Avoids large documents, better for queries and updates /// public class ProductRef { public ObjectId Id { get; set; } public string Name { get; set; } = string.Empty; public decimal Price { get; set; } public List? CategoryIds { get; set; } // Only IDs - no embedding } // ======================================== // Nullable String Key Test (UuidEntity scenario) // ======================================== /// /// Base entity class that simulates CleanCore's BaseEntity{TId, TEntity} /// This is the root of the hierarchy that causes the generator bug /// public abstract class MockBaseEntity where TId : IEquatable where TEntity : class { [System.ComponentModel.DataAnnotations.Key] public virtual TId? Id { get; set; } protected MockBaseEntity() { } protected MockBaseEntity(TId? id) { Id = id; } } /// /// Simulates CleanCore's UuidEntity{TEntity} which inherits from BaseEntity{string, TEntity} /// Tests the bug where generator incorrectly chooses ObjectIdMapperBase instead of StringMapperBase /// when the Id property is inherited and nullable /// public abstract class MockUuidEntity : MockBaseEntity where TEntity : class { protected MockUuidEntity() : base() { } protected MockUuidEntity(string? id) : base(id) { } } /// /// Concrete entity that inherits from MockUuidEntity, simulating Counter from CleanCore /// This is the actual entity that will be stored in the collection /// public class MockCounter : MockUuidEntity { public MockCounter() : base() { } public MockCounter(string? id) : base(id) { } public string Name { get; set; } = string.Empty; public int Value { get; set; } } /// /// Entity for testing temporal types: DateTimeOffset, TimeSpan, DateOnly, TimeOnly /// public class TemporalEntity { [Key] public ObjectId Id { get; set; } public string Name { get; set; } = string.Empty; // DateTime types public DateTime CreatedAt { get; set; } public DateTimeOffset UpdatedAt { get; set; } public DateTimeOffset? LastAccessedAt { get; set; } // TimeSpan public TimeSpan Duration { get; set; } public TimeSpan? OptionalDuration { get; set; } // DateOnly and TimeOnly (.NET 6+) public DateOnly BirthDate { get; set; } public DateOnly? Anniversary { get; set; } public TimeOnly OpeningTime { get; set; } public TimeOnly? ClosingTime { get; set; } } }