diff options
Diffstat (limited to 'Jellyfin.Data/Entities/Libraries')
37 files changed, 2484 insertions, 0 deletions
diff --git a/Jellyfin.Data/Entities/Libraries/Artwork.cs b/Jellyfin.Data/Entities/Libraries/Artwork.cs new file mode 100644 index 000000000..7be22af25 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Artwork.cs @@ -0,0 +1,81 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Enums; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing artwork. + /// </summary> + public class Artwork : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="Artwork"/> class. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="kind">The kind of art.</param> + /// <param name="owner">The owner.</param> + public Artwork(string path, ArtKind kind, IHasArtwork owner) + { + if (string.IsNullOrEmpty(path)) + { + throw new ArgumentNullException(nameof(path)); + } + + Path = path; + Kind = kind; + + owner?.Artwork.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="Artwork"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected Artwork() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the path. + /// </summary> + /// <remarks> + /// Required, Max length = 65535. + /// </remarks> + [Required] + [MaxLength(65535)] + [StringLength(65535)] + public string Path { get; set; } + + /// <summary> + /// Gets or sets the kind of artwork. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public ArtKind Kind { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Book.cs b/Jellyfin.Data/Entities/Libraries/Book.cs new file mode 100644 index 000000000..8337788dd --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Book.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a book. + /// </summary> + public class Book : LibraryItem, IHasReleases + { + /// <summary> + /// Initializes a new instance of the <see cref="Book"/> class. + /// </summary> + public Book() + { + BookMetadata = new HashSet<BookMetadata>(); + Releases = new HashSet<Release>(); + } + + /// <summary> + /// Gets or sets a collection containing the metadata for this book. + /// </summary> + public virtual ICollection<BookMetadata> BookMetadata { get; protected set; } + + /// <inheritdoc /> + public virtual ICollection<Release> Releases { get; protected set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/BookMetadata.cs b/Jellyfin.Data/Entities/Libraries/BookMetadata.cs new file mode 100644 index 000000000..bd716712b --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/BookMetadata.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity containing metadata for a book. + /// </summary> + public class BookMetadata : Metadata, IHasCompanies + { + /// <summary> + /// Initializes a new instance of the <see cref="BookMetadata"/> class. + /// </summary> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> + /// <param name="book">The book.</param> + public BookMetadata(string title, string language, Book book) : base(title, language) + { + if (book == null) + { + throw new ArgumentNullException(nameof(book)); + } + + book.BookMetadata.Add(this); + + Publishers = new HashSet<Company>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="BookMetadata"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected BookMetadata() + { + } + + /// <summary> + /// Gets or sets the ISBN. + /// </summary> + public long? Isbn { get; set; } + + /// <summary> + /// Gets or sets a collection of the publishers for this book. + /// </summary> + public virtual ICollection<Company> Publishers { get; protected set; } + + /// <inheritdoc /> + [NotMapped] + public ICollection<Company> Companies => Publishers; + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Chapter.cs b/Jellyfin.Data/Entities/Libraries/Chapter.cs new file mode 100644 index 000000000..d9293c3cc --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Chapter.cs @@ -0,0 +1,102 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a chapter. + /// </summary> + public class Chapter : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="Chapter"/> class. + /// </summary> + /// <param name="language">ISO-639-3 3-character language codes.</param> + /// <param name="startTime">The start time for this chapter.</param> + /// <param name="release">The release.</param> + public Chapter(string language, long startTime, Release release) + { + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + + Language = language; + StartTime = startTime; + + if (release == null) + { + throw new ArgumentNullException(nameof(release)); + } + + release.Chapters.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="Chapter"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected Chapter() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Name { get; set; } + + /// <summary> + /// Gets or sets the language. + /// </summary> + /// <remarks> + /// Required, Min length = 3, Max length = 3 + /// ISO-639-3 3-character language codes. + /// </remarks> + [Required] + [MinLength(3)] + [MaxLength(3)] + [StringLength(3)] + public string Language { get; set; } + + /// <summary> + /// Gets or sets the start time. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public long StartTime { get; set; } + + /// <summary> + /// Gets or sets the end time. + /// </summary> + public long? EndTime { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; protected set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Collection.cs b/Jellyfin.Data/Entities/Libraries/Collection.cs new file mode 100644 index 000000000..2e1bbcfb6 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Collection.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a collection. + /// </summary> + public class Collection : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="Collection"/> class. + /// </summary> + public Collection() + { + Items = new HashSet<CollectionItem>(); + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Name { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <summary> + /// Gets or sets a collection containing this collection's items. + /// </summary> + public virtual ICollection<CollectionItem> Items { get; protected set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/CollectionItem.cs b/Jellyfin.Data/Entities/Libraries/CollectionItem.cs new file mode 100644 index 000000000..c9306f630 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/CollectionItem.cs @@ -0,0 +1,94 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a collection item. + /// </summary> + public class CollectionItem : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="CollectionItem"/> class. + /// </summary> + /// <param name="collection">The collection.</param> + /// <param name="previous">The previous item.</param> + /// <param name="next">The next item.</param> + public CollectionItem(Collection collection, CollectionItem previous, CollectionItem next) + { + if (collection == null) + { + throw new ArgumentNullException(nameof(collection)); + } + + collection.Items.Add(this); + + if (next != null) + { + Next = next; + next.Previous = this; + } + + if (previous != null) + { + Previous = previous; + previous.Next = this; + } + } + + /// <summary> + /// Initializes a new instance of the <see cref="CollectionItem"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected CollectionItem() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <summary> + /// Gets or sets the library item. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public virtual LibraryItem LibraryItem { get; set; } + + /// <summary> + /// Gets or sets the next item in the collection. + /// </summary> + /// <remarks> + /// TODO check if this properly updated dependant and has the proper principal relationship + /// </remarks> + public virtual CollectionItem Next { get; set; } + + /// <summary> + /// Gets or sets the previous item in the collection. + /// </summary> + /// <remarks> + /// TODO check if this properly updated dependant and has the proper principal relationship + /// </remarks> + public virtual CollectionItem Previous { get; set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Company.cs b/Jellyfin.Data/Entities/Libraries/Company.cs new file mode 100644 index 000000000..02da26bc2 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Company.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a company. + /// </summary> + public class Company : IHasCompanies, IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="Company"/> class. + /// </summary> + /// <param name="owner">The owner of this company.</param> + public Company(IHasCompanies owner) + { + owner?.Companies.Add(this); + + CompanyMetadata = new HashSet<CompanyMetadata>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="Company"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected Company() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <summary> + /// Gets or sets a collection containing the metadata. + /// </summary> + public virtual ICollection<CompanyMetadata> CompanyMetadata { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing this company's child companies. + /// </summary> + public virtual ICollection<Company> ChildCompanies { get; protected set; } + + /// <inheritdoc /> + [NotMapped] + public ICollection<Company> Companies => ChildCompanies; + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs b/Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs new file mode 100644 index 000000000..60cc96a34 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs @@ -0,0 +1,74 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity holding metadata for a <see cref="Company"/>. + /// </summary> + public class CompanyMetadata : Metadata + { + /// <summary> + /// Initializes a new instance of the <see cref="CompanyMetadata"/> class. + /// </summary> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> + /// <param name="company">The company.</param> + public CompanyMetadata(string title, string language, Company company) : base(title, language) + { + if (company == null) + { + throw new ArgumentNullException(nameof(company)); + } + + company.CompanyMetadata.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="CompanyMetadata"/> class. + /// </summary> + protected CompanyMetadata() + { + } + + /// <summary> + /// Gets or sets the description. + /// </summary> + /// <remarks> + /// Max length = 65535. + /// </remarks> + [MaxLength(65535)] + [StringLength(65535)] + public string Description { get; set; } + + /// <summary> + /// Gets or sets the headquarters. + /// </summary> + /// <remarks> + /// Max length = 255. + /// </remarks> + [MaxLength(255)] + [StringLength(255)] + public string Headquarters { get; set; } + + /// <summary> + /// Gets or sets the country code. + /// </summary> + /// <remarks> + /// Max length = 2. + /// </remarks> + [MaxLength(2)] + [StringLength(2)] + public string Country { get; set; } + + /// <summary> + /// Gets or sets the homepage. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Homepage { get; set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/CustomItem.cs b/Jellyfin.Data/Entities/Libraries/CustomItem.cs new file mode 100644 index 000000000..6a4f0a537 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/CustomItem.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a custom item. + /// </summary> + public class CustomItem : LibraryItem, IHasReleases + { + /// <summary> + /// Initializes a new instance of the <see cref="CustomItem"/> class. + /// </summary> + public CustomItem() + { + CustomItemMetadata = new HashSet<CustomItemMetadata>(); + Releases = new HashSet<Release>(); + } + + /// <summary> + /// Gets or sets a collection containing the metadata for this item. + /// </summary> + public virtual ICollection<CustomItemMetadata> CustomItemMetadata { get; protected set; } + + /// <inheritdoc /> + public virtual ICollection<Release> Releases { get; protected set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs b/Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs new file mode 100644 index 000000000..bc1835528 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs @@ -0,0 +1,36 @@ +using System; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity containing metadata for a custom item. + /// </summary> + public class CustomItemMetadata : Metadata + { + /// <summary> + /// Initializes a new instance of the <see cref="CustomItemMetadata"/> class. + /// </summary> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> + /// <param name="item">The item.</param> + public CustomItemMetadata(string title, string language, CustomItem item) : base(title, language) + { + if (item == null) + { + throw new ArgumentNullException(nameof(item)); + } + + item.CustomItemMetadata.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="CustomItemMetadata"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected CustomItemMetadata() + { + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Episode.cs b/Jellyfin.Data/Entities/Libraries/Episode.cs new file mode 100644 index 000000000..430a11e3c --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Episode.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing an episode. + /// </summary> + public class Episode : LibraryItem, IHasReleases + { + /// <summary> + /// Initializes a new instance of the <see cref="Episode"/> class. + /// </summary> + /// <param name="season">The season.</param> + public Episode(Season season) + { + if (season == null) + { + throw new ArgumentNullException(nameof(season)); + } + + season.Episodes.Add(this); + + Releases = new HashSet<Release>(); + EpisodeMetadata = new HashSet<EpisodeMetadata>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="Episode"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected Episode() + { + } + + /// <summary> + /// Gets or sets the episode number. + /// </summary> + public int? EpisodeNumber { get; set; } + + /// <inheritdoc /> + public virtual ICollection<Release> Releases { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing the metadata for this episode. + /// </summary> + public virtual ICollection<EpisodeMetadata> EpisodeMetadata { get; protected set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs b/Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs new file mode 100644 index 000000000..348100cb4 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs @@ -0,0 +1,67 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity containing metadata for an <see cref="Episode"/>. + /// </summary> + public class EpisodeMetadata : Metadata + { + /// <summary> + /// Initializes a new instance of the <see cref="EpisodeMetadata"/> class. + /// </summary> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> + /// <param name="episode">The episode.</param> + public EpisodeMetadata(string title, string language, Episode episode) : base(title, language) + { + if (episode == null) + { + throw new ArgumentNullException(nameof(episode)); + } + + episode.EpisodeMetadata.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="EpisodeMetadata"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected EpisodeMetadata() + { + } + + /// <summary> + /// Gets or sets the outline. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Outline { get; set; } + + /// <summary> + /// Gets or sets the plot. + /// </summary> + /// <remarks> + /// Max length = 65535. + /// </remarks> + [MaxLength(65535)] + [StringLength(65535)] + public string Plot { get; set; } + + /// <summary> + /// Gets or sets the tagline. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Tagline { get; set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Genre.cs b/Jellyfin.Data/Entities/Libraries/Genre.cs new file mode 100644 index 000000000..aeedd7bfd --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Genre.cs @@ -0,0 +1,75 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a genre. + /// </summary> + public class Genre : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="Genre"/> class. + /// </summary> + /// <param name="name">The name.</param> + /// <param name="metadata">The metadata.</param> + public Genre(string name, Metadata metadata) + { + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); + } + + Name = name; + + if (metadata == null) + { + throw new ArgumentNullException(nameof(metadata)); + } + + metadata.Genres.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="Genre"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected Genre() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <remarks> + /// Indexed, Required, Max length = 255. + /// </remarks> + [Required] + [MaxLength(255)] + [StringLength(255)] + public string Name { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; protected set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Library.cs b/Jellyfin.Data/Entities/Libraries/Library.cs new file mode 100644 index 000000000..4f82a2e2a --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Library.cs @@ -0,0 +1,76 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a library. + /// </summary> + public class Library : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="Library"/> class. + /// </summary> + /// <param name="name">The name of the library.</param> + public Library(string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentNullException(nameof(name)); + } + + Name = name; + } + + /// <summary> + /// Initializes a new instance of the <see cref="Library"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected Library() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <remarks> + /// Required, Max length = 128. + /// </remarks> + [Required] + [MaxLength(128)] + [StringLength(128)] + public string Name { get; set; } + + /// <summary> + /// Gets or sets the root path of the library. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + [Required] + public string Path { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/LibraryItem.cs b/Jellyfin.Data/Entities/Libraries/LibraryItem.cs new file mode 100644 index 000000000..a9167aa7f --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/LibraryItem.cs @@ -0,0 +1,63 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a library item. + /// </summary> + public abstract class LibraryItem : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="LibraryItem"/> class. + /// </summary> + /// <param name="library">The library of this item.</param> + protected LibraryItem(Library library) + { + DateAdded = DateTime.UtcNow; + Library = library; + } + + /// <summary> + /// Initializes a new instance of the <see cref="LibraryItem"/> class. + /// </summary> + protected LibraryItem() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the date this library item was added. + /// </summary> + public DateTime DateAdded { get; protected set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; protected set; } + + /// <summary> + /// Gets or sets the library of this item. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + [Required] + public virtual Library Library { get; set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/MediaFile.cs b/Jellyfin.Data/Entities/Libraries/MediaFile.cs new file mode 100644 index 000000000..8bc649c98 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/MediaFile.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Enums; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a file on disk. + /// </summary> + public class MediaFile : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="MediaFile"/> class. + /// </summary> + /// <param name="path">The path relative to the LibraryRoot.</param> + /// <param name="kind">The file kind.</param> + /// <param name="release">The release.</param> + public MediaFile(string path, MediaFileKind kind, Release release) + { + if (string.IsNullOrEmpty(path)) + { + throw new ArgumentNullException(nameof(path)); + } + + Path = path; + Kind = kind; + + if (release == null) + { + throw new ArgumentNullException(nameof(release)); + } + + release.MediaFiles.Add(this); + + MediaFileStreams = new HashSet<MediaFileStream>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="MediaFile"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected MediaFile() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the path relative to the library root. + /// </summary> + /// <remarks> + /// Required, Max length = 65535. + /// </remarks> + [Required] + [MaxLength(65535)] + [StringLength(65535)] + public string Path { get; set; } + + /// <summary> + /// Gets or sets the kind of media file. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public MediaFileKind Kind { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <summary> + /// Gets or sets a collection containing the streams in this file. + /// </summary> + public virtual ICollection<MediaFileStream> MediaFileStreams { get; protected set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs b/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs new file mode 100644 index 000000000..5b03e260e --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs @@ -0,0 +1,67 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a stream in a media file. + /// </summary> + public class MediaFileStream : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="MediaFileStream"/> class. + /// </summary> + /// <param name="streamNumber">The number of this stream.</param> + /// <param name="mediaFile">The media file.</param> + public MediaFileStream(int streamNumber, MediaFile mediaFile) + { + StreamNumber = streamNumber; + + if (mediaFile == null) + { + throw new ArgumentNullException(nameof(mediaFile)); + } + + mediaFile.MediaFileStreams.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="MediaFileStream"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected MediaFileStream() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the stream number. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public int StreamNumber { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Metadata.cs b/Jellyfin.Data/Entities/Libraries/Metadata.cs new file mode 100644 index 000000000..877bb5fbd --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Metadata.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An abstract class that holds metadata. + /// </summary> + public abstract class Metadata : IHasArtwork, IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="Metadata"/> class. + /// </summary> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> + protected Metadata(string title, string language) + { + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + + Title = title; + Language = language; + DateAdded = DateTime.UtcNow; + DateModified = DateAdded; + + PersonRoles = new HashSet<PersonRole>(); + Genres = new HashSet<Genre>(); + Artwork = new HashSet<Artwork>(); + Ratings = new HashSet<Rating>(); + Sources = new HashSet<MetadataProviderId>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="Metadata"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to being abstract. + /// </remarks> + protected Metadata() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the title. + /// </summary> + /// <remarks> + /// Required, Max length = 1024. + /// </remarks> + [Required] + [MaxLength(1024)] + [StringLength(1024)] + public string Title { get; set; } + + /// <summary> + /// Gets or sets the original title. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string OriginalTitle { get; set; } + + /// <summary> + /// Gets or sets the sort title. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string SortTitle { get; set; } + + /// <summary> + /// Gets or sets the language. + /// </summary> + /// <remarks> + /// Required, Min length = 3, Max length = 3. + /// ISO-639-3 3-character language codes. + /// </remarks> + [Required] + [MinLength(3)] + [MaxLength(3)] + [StringLength(3)] + public string Language { get; set; } + + /// <summary> + /// Gets or sets the release date. + /// </summary> + public DateTimeOffset? ReleaseDate { get; set; } + + /// <summary> + /// Gets or sets the date added. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public DateTime DateAdded { get; protected set; } + + /// <summary> + /// Gets or sets the date modified. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public DateTime DateModified { get; set; } + + /// <summary> + /// Gets or sets the row version. + /// </summary> + /// <remarks> + /// Required, ConcurrencyToken. + /// </remarks> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <summary> + /// Gets or sets a collection containing the person roles for this item. + /// </summary> + public virtual ICollection<PersonRole> PersonRoles { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing the generes for this item. + /// </summary> + public virtual ICollection<Genre> Genres { get; protected set; } + + /// <inheritdoc /> + public virtual ICollection<Artwork> Artwork { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing the ratings for this item. + /// </summary> + public virtual ICollection<Rating> Ratings { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing the metadata sources for this item. + /// </summary> + public virtual ICollection<MetadataProviderId> Sources { get; protected set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/MetadataProvider.cs b/Jellyfin.Data/Entities/Libraries/MetadataProvider.cs new file mode 100644 index 000000000..a18a612bc --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/MetadataProvider.cs @@ -0,0 +1,67 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a metadata provider. + /// </summary> + public class MetadataProvider : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="MetadataProvider"/> class. + /// </summary> + /// <param name="name">The name of the metadata provider.</param> + public MetadataProvider(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); + } + + Name = name; + } + + /// <summary> + /// Initializes a new instance of the <see cref="MetadataProvider"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected MetadataProvider() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <remarks> + /// Required, Max length = 1024. + /// </remarks> + [Required] + [MaxLength(1024)] + [StringLength(1024)] + public string Name { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs b/Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs new file mode 100644 index 000000000..6e6de598e --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs @@ -0,0 +1,83 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a unique identifier for a metadata provider. + /// </summary> + public class MetadataProviderId : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="MetadataProviderId"/> class. + /// </summary> + /// <param name="providerId">The provider id.</param> + /// <param name="metadata">The metadata entity.</param> + public MetadataProviderId(string providerId, Metadata metadata) + { + if (string.IsNullOrEmpty(providerId)) + { + throw new ArgumentNullException(nameof(providerId)); + } + + ProviderId = providerId; + + if (metadata == null) + { + throw new ArgumentNullException(nameof(metadata)); + } + + metadata.Sources.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="MetadataProviderId"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected MetadataProviderId() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the provider id. + /// </summary> + /// <remarks> + /// Required, Max length = 255. + /// </remarks> + [Required] + [MaxLength(255)] + [StringLength(255)] + public string ProviderId { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <summary> + /// Gets or sets the metadata provider. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public virtual MetadataProvider MetadataProvider { get; set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Movie.cs b/Jellyfin.Data/Entities/Libraries/Movie.cs new file mode 100644 index 000000000..0a8cc83dd --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Movie.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a movie. + /// </summary> + public class Movie : LibraryItem, IHasReleases + { + /// <summary> + /// Initializes a new instance of the <see cref="Movie"/> class. + /// </summary> + public Movie() + { + Releases = new HashSet<Release>(); + MovieMetadata = new HashSet<MovieMetadata>(); + } + + /// <inheritdoc /> + public virtual ICollection<Release> Releases { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing the metadata for this movie. + /// </summary> + public virtual ICollection<MovieMetadata> MovieMetadata { get; protected set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/MovieMetadata.cs b/Jellyfin.Data/Entities/Libraries/MovieMetadata.cs new file mode 100644 index 000000000..31102bf13 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/MovieMetadata.cs @@ -0,0 +1,85 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity holding the metadata for a movie. + /// </summary> + public class MovieMetadata : Metadata, IHasCompanies + { + /// <summary> + /// Initializes a new instance of the <see cref="MovieMetadata"/> class. + /// </summary> + /// <param name="title">The title or name of the movie.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> + /// <param name="movie">The movie.</param> + public MovieMetadata(string title, string language, Movie movie) : base(title, language) + { + Studios = new HashSet<Company>(); + + movie.MovieMetadata.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="MovieMetadata"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected MovieMetadata() + { + } + + /// <summary> + /// Gets or sets the outline. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Outline { get; set; } + + /// <summary> + /// Gets or sets the tagline. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Tagline { get; set; } + + /// <summary> + /// Gets or sets the plot. + /// </summary> + /// <remarks> + /// Max length = 65535. + /// </remarks> + [MaxLength(65535)] + [StringLength(65535)] + public string Plot { get; set; } + + /// <summary> + /// Gets or sets the country code. + /// </summary> + /// <remarks> + /// Max length = 2. + /// </remarks> + [MaxLength(2)] + [StringLength(2)] + public string Country { get; set; } + + /// <summary> + /// Gets or sets the studios that produced this movie. + /// </summary> + public virtual ICollection<Company> Studios { get; protected set; } + + /// <inheritdoc /> + [NotMapped] + public ICollection<Company> Companies => Studios; + } +} diff --git a/Jellyfin.Data/Entities/Libraries/MusicAlbum.cs b/Jellyfin.Data/Entities/Libraries/MusicAlbum.cs new file mode 100644 index 000000000..2ed1f78c5 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/MusicAlbum.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a music album. + /// </summary> + public class MusicAlbum : LibraryItem + { + /// <summary> + /// Initializes a new instance of the <see cref="MusicAlbum"/> class. + /// </summary> + public MusicAlbum() + { + MusicAlbumMetadata = new HashSet<MusicAlbumMetadata>(); + Tracks = new HashSet<Track>(); + } + + /// <summary> + /// Gets or sets a collection containing the album metadata. + /// </summary> + public virtual ICollection<MusicAlbumMetadata> MusicAlbumMetadata { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing the tracks. + /// </summary> + public virtual ICollection<Track> Tracks { get; protected set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs b/Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs new file mode 100644 index 000000000..cc5919bfe --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity holding the metadata for a music album. + /// </summary> + public class MusicAlbumMetadata : Metadata + { + /// <summary> + /// Initializes a new instance of the <see cref="MusicAlbumMetadata"/> class. + /// </summary> + /// <param name="title">The title or name of the album.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> + /// <param name="album">The music album.</param> + public MusicAlbumMetadata(string title, string language, MusicAlbum album) : base(title, language) + { + Labels = new HashSet<Company>(); + + album.MusicAlbumMetadata.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="MusicAlbumMetadata"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected MusicAlbumMetadata() + { + } + + /// <summary> + /// Gets or sets the barcode. + /// </summary> + /// <remarks> + /// Max length = 255. + /// </remarks> + [MaxLength(255)] + [StringLength(255)] + public string Barcode { get; set; } + + /// <summary> + /// Gets or sets the label number. + /// </summary> + /// <remarks> + /// Max length = 255. + /// </remarks> + [MaxLength(255)] + [StringLength(255)] + public string LabelNumber { get; set; } + + /// <summary> + /// Gets or sets the country code. + /// </summary> + /// <remarks> + /// Max length = 2. + /// </remarks> + [MaxLength(2)] + [StringLength(2)] + public string Country { get; set; } + + /// <summary> + /// Gets or sets a collection containing the labels. + /// </summary> + public virtual ICollection<Company> Labels { get; protected set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Person.cs b/Jellyfin.Data/Entities/Libraries/Person.cs new file mode 100644 index 000000000..8beb3dd08 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Person.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a person. + /// </summary> + public class Person : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="Person"/> class. + /// </summary> + /// <param name="name">The name of the person.</param> + public Person(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); + } + + Name = name; + DateAdded = DateTime.UtcNow; + DateModified = DateAdded; + + Sources = new HashSet<MetadataProviderId>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="Person"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected Person() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <remarks> + /// Required, Max length = 1024. + /// </remarks> + [Required] + [MaxLength(1024)] + [StringLength(1024)] + public string Name { get; set; } + + /// <summary> + /// Gets or sets the source id. + /// </summary> + /// <remarks> + /// Max length = 255. + /// </remarks> + [MaxLength(256)] + [StringLength(256)] + public string SourceId { get; set; } + + /// <summary> + /// Gets or sets the date added. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public DateTime DateAdded { get; protected set; } + + /// <summary> + /// Gets or sets the date modified. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public DateTime DateModified { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <summary> + /// Gets or sets a list of metadata sources for this person. + /// </summary> + public virtual ICollection<MetadataProviderId> Sources { get; protected set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/PersonRole.cs b/Jellyfin.Data/Entities/Libraries/PersonRole.cs new file mode 100644 index 000000000..5290228d6 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/PersonRole.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Enums; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a person's role in media. + /// </summary> + public class PersonRole : IHasArtwork, IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="PersonRole"/> class. + /// </summary> + /// <param name="type">The role type.</param> + /// <param name="metadata">The metadata.</param> + public PersonRole(PersonRoleType type, Metadata metadata) + { + Type = type; + + if (metadata == null) + { + throw new ArgumentNullException(nameof(metadata)); + } + + metadata.PersonRoles.Add(this); + + Sources = new HashSet<MetadataProviderId>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="PersonRole"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected PersonRole() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the name of the person's role. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Role { get; set; } + + /// <summary> + /// Gets or sets the person's role type. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public PersonRoleType Type { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; protected set; } + + /// <summary> + /// Gets or sets the person. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + [Required] + public virtual Person Person { get; set; } + + /// <inheritdoc /> + public virtual ICollection<Artwork> Artwork { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing the metadata sources for this person role. + /// </summary> + public virtual ICollection<MetadataProviderId> Sources { get; protected set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Photo.cs b/Jellyfin.Data/Entities/Libraries/Photo.cs new file mode 100644 index 000000000..44338a4ce --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Photo.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a photo. + /// </summary> + public class Photo : LibraryItem, IHasReleases + { + /// <summary> + /// Initializes a new instance of the <see cref="Photo"/> class. + /// </summary> + public Photo() + { + PhotoMetadata = new HashSet<PhotoMetadata>(); + Releases = new HashSet<Release>(); + } + + /// <summary> + /// Gets or sets a collection containing the photo metadata. + /// </summary> + public virtual ICollection<PhotoMetadata> PhotoMetadata { get; protected set; } + + /// <inheritdoc /> + public virtual ICollection<Release> Releases { get; protected set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs b/Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs new file mode 100644 index 000000000..1ef9dd5f9 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs @@ -0,0 +1,36 @@ +using System; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity that holds metadata for a photo. + /// </summary> + public class PhotoMetadata : Metadata + { + /// <summary> + /// Initializes a new instance of the <see cref="PhotoMetadata"/> class. + /// </summary> + /// <param name="title">The title or name of the photo.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> + /// <param name="photo">The photo.</param> + public PhotoMetadata(string title, string language, Photo photo) : base(title, language) + { + if (photo == null) + { + throw new ArgumentNullException(nameof(photo)); + } + + photo.PhotoMetadata.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="PhotoMetadata"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected PhotoMetadata() + { + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Rating.cs b/Jellyfin.Data/Entities/Libraries/Rating.cs new file mode 100644 index 000000000..ba054a39e --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Rating.cs @@ -0,0 +1,78 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a rating for an entity. + /// </summary> + public class Rating : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="Rating"/> class. + /// </summary> + /// <param name="value">The value.</param> + /// <param name="metadata">The metadata.</param> + public Rating(double value, Metadata metadata) + { + Value = value; + + if (metadata == null) + { + throw new ArgumentNullException(nameof(metadata)); + } + + metadata.Ratings.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="Rating"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected Rating() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the value. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public double Value { get; set; } + + /// <summary> + /// Gets or sets the number of votes. + /// </summary> + public int? Votes { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <summary> + /// Gets or sets the rating type. + /// If this is <c>null</c> it's the internal user rating. + /// </summary> + public virtual RatingSource RatingType { get; set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/RatingSource.cs b/Jellyfin.Data/Entities/Libraries/RatingSource.cs new file mode 100644 index 000000000..549f41804 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/RatingSource.cs @@ -0,0 +1,92 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// This is the entity to store review ratings, not age ratings. + /// </summary> + public class RatingSource : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="RatingSource"/> class. + /// </summary> + /// <param name="minimumValue">The minimum value.</param> + /// <param name="maximumValue">The maximum value.</param> + /// <param name="rating">The rating.</param> + public RatingSource(double minimumValue, double maximumValue, Rating rating) + { + MinimumValue = minimumValue; + MaximumValue = maximumValue; + + if (rating == null) + { + throw new ArgumentNullException(nameof(rating)); + } + + rating.RatingType = this; + } + + /// <summary> + /// Initializes a new instance of the <see cref="RatingSource"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected RatingSource() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Name { get; set; } + + /// <summary> + /// Gets or sets the minimum value. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public double MinimumValue { get; set; } + + /// <summary> + /// Gets or sets the maximum value. + /// </summary> + /// <remarks> + /// Required. + /// </remarks> + public double MaximumValue { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <summary> + /// Gets or sets the metadata source. + /// </summary> + public virtual MetadataProviderId Source { get; set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Release.cs b/Jellyfin.Data/Entities/Libraries/Release.cs new file mode 100644 index 000000000..43c7080d7 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Release.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a release for a library item, eg. Director's cut vs. standard. + /// </summary> + public class Release : IHasConcurrencyToken + { + /// <summary> + /// Initializes a new instance of the <see cref="Release"/> class. + /// </summary> + /// <param name="name">The name of this release.</param> + /// <param name="owner">The owner of this release.</param> + public Release(string name, IHasReleases owner) + { + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); + } + + Name = name; + + owner?.Releases.Add(this); + + MediaFiles = new HashSet<MediaFile>(); + Chapters = new HashSet<Chapter>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="Release"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected Release() + { + } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <remarks> + /// Identity, Indexed, Required. + /// </remarks> + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <remarks> + /// Required, Max length = 1024. + /// </remarks> + [Required] + [MaxLength(1024)] + [StringLength(1024)] + public string Name { get; set; } + + /// <inheritdoc /> + [ConcurrencyCheck] + public uint RowVersion { get; set; } + + /// <summary> + /// Gets or sets a collection containing the media files for this release. + /// </summary> + public virtual ICollection<MediaFile> MediaFiles { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing the chapters for this release. + /// </summary> + public virtual ICollection<Chapter> Chapters { get; protected set; } + + /// <inheritdoc /> + public void OnSavingChanges() + { + RowVersion++; + } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Season.cs b/Jellyfin.Data/Entities/Libraries/Season.cs new file mode 100644 index 000000000..eef788bad --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Season.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a season. + /// </summary> + public class Season : LibraryItem + { + /// <summary> + /// Initializes a new instance of the <see cref="Season"/> class. + /// </summary> + /// <param name="series">The series.</param> + public Season(Series series) + { + if (series == null) + { + throw new ArgumentNullException(nameof(series)); + } + + series.Seasons.Add(this); + + Episodes = new HashSet<Episode>(); + SeasonMetadata = new HashSet<SeasonMetadata>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="Season"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected Season() + { + } + + /// <summary> + /// Gets or sets the season number. + /// </summary> + public int? SeasonNumber { get; set; } + + /// <summary> + /// Gets or sets the season metadata. + /// </summary> + public virtual ICollection<SeasonMetadata> SeasonMetadata { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing the number of episodes. + /// </summary> + public virtual ICollection<Episode> Episodes { get; protected set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs b/Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs new file mode 100644 index 000000000..eedeb089e --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs @@ -0,0 +1,47 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity that holds metadata for seasons. + /// </summary> + public class SeasonMetadata : Metadata + { + /// <summary> + /// Initializes a new instance of the <see cref="SeasonMetadata"/> class. + /// </summary> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> + /// <param name="season">The season.</param> + public SeasonMetadata(string title, string language, Season season) : base(title, language) + { + if (season == null) + { + throw new ArgumentNullException(nameof(season)); + } + + season.SeasonMetadata.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="SeasonMetadata"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected SeasonMetadata() + { + } + + /// <summary> + /// Gets or sets the outline. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Outline { get; set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Series.cs b/Jellyfin.Data/Entities/Libraries/Series.cs new file mode 100644 index 000000000..e959c1fe0 --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Series.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a a series. + /// </summary> + public class Series : LibraryItem + { + /// <summary> + /// Initializes a new instance of the <see cref="Series"/> class. + /// </summary> + public Series() + { + DateAdded = DateTime.UtcNow; + Seasons = new HashSet<Season>(); + SeriesMetadata = new HashSet<SeriesMetadata>(); + } + + /// <summary> + /// Gets or sets the days of week. + /// </summary> + public DayOfWeek? AirsDayOfWeek { get; set; } + + /// <summary> + /// Gets or sets the time the show airs, ignore the date portion. + /// </summary> + public DateTimeOffset? AirsTime { get; set; } + + /// <summary> + /// Gets or sets the date the series first aired. + /// </summary> + public DateTime? FirstAired { get; set; } + + /// <summary> + /// Gets or sets a collection containing the series metadata. + /// </summary> + public virtual ICollection<SeriesMetadata> SeriesMetadata { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing the seasons. + /// </summary> + public virtual ICollection<Season> Seasons { get; protected set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs b/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs new file mode 100644 index 000000000..898f3006d --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing series metadata. + /// </summary> + public class SeriesMetadata : Metadata, IHasCompanies + { + /// <summary> + /// Initializes a new instance of the <see cref="SeriesMetadata"/> class. + /// </summary> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> + /// <param name="series">The series.</param> + public SeriesMetadata(string title, string language, Series series) : base(title, language) + { + if (series == null) + { + throw new ArgumentNullException(nameof(series)); + } + + series.SeriesMetadata.Add(this); + + Networks = new HashSet<Company>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="SeriesMetadata"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected SeriesMetadata() + { + } + + /// <summary> + /// Gets or sets the outline. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Outline { get; set; } + + /// <summary> + /// Gets or sets the plot. + /// </summary> + /// <remarks> + /// Max length = 65535. + /// </remarks> + [MaxLength(65535)] + [StringLength(65535)] + public string Plot { get; set; } + + /// <summary> + /// Gets or sets the tagline. + /// </summary> + /// <remarks> + /// Max length = 1024. + /// </remarks> + [MaxLength(1024)] + [StringLength(1024)] + public string Tagline { get; set; } + + /// <summary> + /// Gets or sets the country code. + /// </summary> + /// <remarks> + /// Max length = 2. + /// </remarks> + [MaxLength(2)] + [StringLength(2)] + public string Country { get; set; } + + /// <summary> + /// Gets or sets a collection containing the networks. + /// </summary> + public virtual ICollection<Company> Networks { get; protected set; } + + /// <inheritdoc /> + [NotMapped] + public ICollection<Company> Companies => Networks; + } +} diff --git a/Jellyfin.Data/Entities/Libraries/Track.cs b/Jellyfin.Data/Entities/Libraries/Track.cs new file mode 100644 index 000000000..09ce82a9b --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/Track.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using Jellyfin.Data.Interfaces; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity representing a track. + /// </summary> + public class Track : LibraryItem, IHasReleases + { + /// <summary> + /// Initializes a new instance of the <see cref="Track"/> class. + /// </summary> + /// <param name="album">The album.</param> + public Track(MusicAlbum album) + { + if (album == null) + { + throw new ArgumentNullException(nameof(album)); + } + + album.Tracks.Add(this); + + Releases = new HashSet<Release>(); + TrackMetadata = new HashSet<TrackMetadata>(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="Track"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected Track() + { + } + + /// <summary> + /// Gets or sets the track number. + /// </summary> + public int? TrackNumber { get; set; } + + /// <inheritdoc /> + public virtual ICollection<Release> Releases { get; protected set; } + + /// <summary> + /// Gets or sets a collection containing the track metadata. + /// </summary> + public virtual ICollection<TrackMetadata> TrackMetadata { get; protected set; } + } +} diff --git a/Jellyfin.Data/Entities/Libraries/TrackMetadata.cs b/Jellyfin.Data/Entities/Libraries/TrackMetadata.cs new file mode 100644 index 000000000..048068a1a --- /dev/null +++ b/Jellyfin.Data/Entities/Libraries/TrackMetadata.cs @@ -0,0 +1,36 @@ +using System; + +namespace Jellyfin.Data.Entities.Libraries +{ + /// <summary> + /// An entity holding metadata for a track. + /// </summary> + public class TrackMetadata : Metadata + { + /// <summary> + /// Initializes a new instance of the <see cref="TrackMetadata"/> class. + /// </summary> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> + /// <param name="track">The track.</param> + public TrackMetadata(string title, string language, Track track) : base(title, language) + { + if (track == null) + { + throw new ArgumentNullException(nameof(track)); + } + + track.TrackMetadata.Add(this); + } + + /// <summary> + /// Initializes a new instance of the <see cref="TrackMetadata"/> class. + /// </summary> + /// <remarks> + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// </remarks> + protected TrackMetadata() + { + } + } +} |
