using MediaBrowser.Controller.Library; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Controller.Entities { /// /// Specialized Folder class that points to a subset of the physical folders in the system. /// It is created from the user-specific folders within the system root /// public class CollectionFolder : Folder, ICollectionFolder { /// /// Gets a value indicating whether this instance is virtual folder. /// /// true if this instance is virtual folder; otherwise, false. [IgnoreDataMember] public override bool IsVirtualFolder { get { return true; } } public string CollectionType { get; set; } /// /// Allow different display preferences for each collection folder /// /// The display prefs id. public override Guid DisplayPreferencesId { get { return Id; } } // Cache this since it will be used a lot /// /// The null task result /// private static readonly Task NullTaskResult = Task.FromResult(null); /// /// Compare our current children (presumably just read from the repo) with the current state of the file system and adjust for any changes /// ***Currently does not contain logic to maintain items that are unavailable in the file system*** /// /// The progress. /// The cancellation token. /// if set to true [recursive]. /// if set to true [force refresh metadata]. /// Task. protected override Task ValidateChildrenInternal(IProgress progress, CancellationToken cancellationToken, bool? recursive = null, bool forceRefreshMetadata = false) { //we don't directly validate our children //but we do need to clear out the index cache... IndexCache = new ConcurrentDictionary>(StringComparer.OrdinalIgnoreCase); return NullTaskResult; } /// /// Our children are actually just references to the ones in the physical root... /// /// The linked children. public override List LinkedChildren { get { ItemResolveArgs resolveArgs; try { resolveArgs = ResolveArgs; } catch (IOException ex) { Logger.ErrorException("Error getting ResolveArgs for {0}", ex, Path); return new List(); } return LibraryManager.RootFolder.RecursiveChildren .OfType() .Where(i => i.Path != null && resolveArgs.PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase)) .SelectMany(c => c.LinkedChildren).ToList(); } set { base.LinkedChildren = value; } } /// /// Our children are actually just references to the ones in the physical root... /// /// The actual children. protected override ConcurrentDictionary ActualChildren { get { ItemResolveArgs resolveArgs; try { resolveArgs = ResolveArgs; } catch (IOException ex) { Logger.ErrorException("Error getting ResolveArgs for {0}", ex, Path); return new ConcurrentDictionary(); } var ourChildren = LibraryManager.RootFolder.RecursiveChildren .OfType() .Where(i => i.Path != null && resolveArgs.PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase)) .SelectMany(c => c.Children); return new ConcurrentDictionary(ourChildren.ToDictionary(i => i.Id)); } } } }