123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- using MediaBrowser.Common.Extensions;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq;
- using System.Runtime.Serialization;
- using System.Threading;
- using System.Threading.Tasks;
- namespace MediaBrowser.Controller.Entities
- {
- /// <summary>
- /// Class IndexFolder
- /// </summary>
- public class IndexFolder : Folder
- {
- /// <summary>
- /// Initializes a new instance of the <see cref="IndexFolder" /> class.
- /// </summary>
- /// <param name="parent">The parent.</param>
- /// <param name="shadow">The shadow.</param>
- /// <param name="children">The children.</param>
- /// <param name="indexName">Name of the index.</param>
- /// <param name="groupContents">if set to <c>true</c> [group contents].</param>
- public IndexFolder(Folder parent, BaseItem shadow, IEnumerable<BaseItem> children, string indexName, bool groupContents = true)
- {
- ChildSource = children;
- ShadowItem = shadow;
- GroupContents = groupContents;
- if (shadow == null)
- {
- Name = ForcedSortName = "<Unknown>";
- }
- else
- {
- SetShadowValues();
- }
- Id = (parent.Id.ToString() + Name).GetMBId(typeof(IndexFolder));
- IndexName = indexName;
- Parent = parent;
- }
- /// <summary>
- /// Resets the parent.
- /// </summary>
- /// <param name="parent">The parent.</param>
- public void ResetParent(Folder parent)
- {
- Parent = parent;
- Id = (parent.Id.ToString() + Name).GetMBId(typeof(IndexFolder));
- }
- /// <summary>
- /// Override this to true if class should be grouped under a container in indicies
- /// The container class should be defined via IndexContainer
- /// </summary>
- /// <value><c>true</c> if [group in index]; otherwise, <c>false</c>.</value>
- [IgnoreDataMember]
- public override bool GroupInIndex
- {
- get
- {
- return ShadowItem != null && ShadowItem.GroupInIndex;
- }
- }
- /// <summary>
- /// Override this to return the folder that should be used to construct a container
- /// for this item in an index. GroupInIndex should be true as well.
- /// </summary>
- /// <value>The index container.</value>
- [IgnoreDataMember]
- public override Folder IndexContainer
- {
- get { return ShadowItem != null ? ShadowItem.IndexContainer : new IndexFolder(this, null, null, "<Unknown>", false); }
- }
- /// <summary>
- /// Gets or sets a value indicating whether [group contents].
- /// </summary>
- /// <value><c>true</c> if [group contents]; otherwise, <c>false</c>.</value>
- protected bool GroupContents { get; set; }
- /// <summary>
- /// Gets or sets the child source.
- /// </summary>
- /// <value>The child source.</value>
- protected IEnumerable<BaseItem> ChildSource { get; set; }
- /// <summary>
- /// Gets or sets our children.
- /// </summary>
- /// <value>Our children.</value>
- protected ConcurrentBag<BaseItem> OurChildren { get; set; }
- /// <summary>
- /// Gets the name of the index.
- /// </summary>
- /// <value>The name of the index.</value>
- public string IndexName { get; private set; }
- /// <summary>
- /// Override to return the children defined to us when we were created
- /// </summary>
- /// <value>The actual children.</value>
- protected override ConcurrentBag<BaseItem> LoadChildren()
- {
- var originalChildSource = ChildSource.ToList();
- var kids = originalChildSource;
- if (GroupContents)
- {
- // Recursively group up the chain
- var group = true;
- var isSubsequentLoop = false;
- while (group)
- {
- kids = isSubsequentLoop || kids.Any(i => i.GroupInIndex)
- ? GroupedSource(kids).ToList()
- : originalChildSource;
- group = kids.Any(i => i.GroupInIndex);
- isSubsequentLoop = true;
- }
- }
- // Now - since we built the index grouping from the bottom up - we now need to properly set Parents from the top down
- SetParents(this, kids.OfType<IndexFolder>());
- return new ConcurrentBag<BaseItem>(kids);
- }
- /// <summary>
- /// Sets the parents.
- /// </summary>
- /// <param name="parent">The parent.</param>
- /// <param name="kids">The kids.</param>
- private void SetParents(Folder parent, IEnumerable<IndexFolder> kids)
- {
- foreach (var child in kids)
- {
- child.ResetParent(parent);
- child.SetParents(child, child.Children.OfType<IndexFolder>());
- }
- }
- /// <summary>
- /// Groupeds the source.
- /// </summary>
- /// <param name="source">The source.</param>
- /// <returns>IEnumerable{BaseItem}.</returns>
- protected IEnumerable<BaseItem> GroupedSource(IEnumerable<BaseItem> source)
- {
- return source.GroupBy(i => i.IndexContainer).Select(container => new IndexFolder(this, container.Key, container, null, false));
- }
- /// <summary>
- /// The item we are shadowing as a folder (Genre, Actor, etc.)
- /// We inherit the images and other meta from this item
- /// </summary>
- /// <value>The shadow item.</value>
- protected BaseItem ShadowItem { get; set; }
- /// <summary>
- /// Sets the shadow values.
- /// </summary>
- protected void SetShadowValues()
- {
- if (ShadowItem != null)
- {
- Name = ShadowItem.Name;
- ForcedSortName = ShadowItem.SortName;
- Genres = ShadowItem.Genres;
- Studios = ShadowItem.Studios;
- OfficialRating = ShadowItem.OfficialRating;
- BackdropImagePaths = ShadowItem.BackdropImagePaths;
- Images = ShadowItem.Images;
- Overview = ShadowItem.Overview;
- DisplayMediaType = ShadowItem.GetType().Name;
- }
- }
- /// <summary>
- /// Overrides the base implementation to refresh metadata for local trailers
- /// </summary>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <param name="forceSave">if set to <c>true</c> [is new item].</param>
- /// <param name="forceRefresh">if set to <c>true</c> [force].</param>
- /// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
- /// <param name="resetResolveArgs">if set to <c>true</c> [reset resolve args].</param>
- /// <returns>Task{System.Boolean}.</returns>
- public override async Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true)
- {
- if (ShadowItem != null)
- {
- var changed = await ShadowItem.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs).ConfigureAwait(false);
- cancellationToken.ThrowIfCancellationRequested();
- SetShadowValues();
- return changed;
- }
- return false;
- }
- }
- }
|