using GermanApp.Domain.Exceptions; namespace GermanApp.Domain.ValueObjects; /// /// Represents a German word with its translation and metadata. /// This is a value object - it has no identity and is defined by its attributes. /// public record GermanWord { public string Value { get; } public string Translation { get; } public string? Article { get; } // der, die, das, or null for verbs/adjectives public string PartOfSpeech { get; } public GermanWord(string value, string translation, string? article, string partOfSpeech) { if (string.IsNullOrWhiteSpace(value)) throw new DomainException("German word cannot be empty"); if (string.IsNullOrWhiteSpace(translation)) throw new DomainException("Translation cannot be empty"); if (string.IsNullOrWhiteSpace(partOfSpeech)) throw new DomainException("Part of speech is required"); if (article != null && !IsValidArticle(article)) throw new DomainException("Invalid article. Must be 'der', 'die', or 'das'"); Value = value.Trim(); Translation = translation.Trim(); Article = article?.Trim(); PartOfSpeech = partOfSpeech.Trim(); } private static bool IsValidArticle(string article) => article.Equals("der", StringComparison.OrdinalIgnoreCase) || article.Equals("die", StringComparison.OrdinalIgnoreCase) || article.Equals("das", StringComparison.OrdinalIgnoreCase); /// /// Check if this word has a definite article. /// public bool HasArticle() => Article != null; /// /// Get the word with its article (if applicable). /// public string GetWithArticle() => Article != null ? $"{Article} {Value}" : Value; }