using MediaBrowser.Controller.IO; 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 MediaBrowser.Controller.Providers; namespace MediaBrowser.Controller.Entities { /// /// Specialized folder that can have items added to it's children by external entities. /// Used for our RootFolder so plug-ins can add items. /// public class AggregateFolder : Folder { public AggregateFolder() { PhysicalLocationsList = new List(); } /// /// We don't support manual shortcuts /// protected override bool SupportsShortcutChildren { get { return false; } } /// /// The _virtual children /// private readonly ConcurrentBag _virtualChildren = new ConcurrentBag(); /// /// Gets the virtual children. /// /// The virtual children. public ConcurrentBag VirtualChildren { get { return _virtualChildren; } } [IgnoreDataMember] public override IEnumerable PhysicalLocations { get { return PhysicalLocationsList; } } public List PhysicalLocationsList { get; set; } protected override IEnumerable GetFileSystemChildren(IDirectoryService directoryService) { return CreateResolveArgs(directoryService).FileSystemChildren; } private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService) { var path = ContainingFolderPath; var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, LibraryManager, directoryService) { FileInfo = new DirectoryInfo(path), Path = path, Parent = Parent }; // Gather child folder and files if (args.IsDirectory) { var isPhysicalRoot = args.IsPhysicalRoot; // When resolving the root, we need it's grandchildren (children of user views) var flattenFolderDepth = isPhysicalRoot ? 2 : 0; var fileSystemDictionary = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf); // Need to remove subpaths that may have been resolved from shortcuts // Example: if \\server\movies exists, then strip out \\server\movies\action if (isPhysicalRoot) { var paths = LibraryManager.NormalizeRootPathList(fileSystemDictionary.Keys); fileSystemDictionary = paths.Select(i => (FileSystemInfo)new DirectoryInfo(i)).ToDictionary(i => i.FullName); } args.FileSystemDictionary = fileSystemDictionary; } PhysicalLocationsList = args.PhysicalLocations.ToList(); return args; } /// /// Adds the virtual child. /// /// The child. /// public void AddVirtualChild(BaseItem child) { if (child == null) { throw new ArgumentNullException(); } _virtualChildren.Add(child); } /// /// Get the children of this folder from the actual file system /// /// IEnumerable{BaseItem}. protected override IEnumerable GetNonCachedChildren(IDirectoryService directoryService) { return base.GetNonCachedChildren(directoryService).Concat(_virtualChildren); } /// /// Finds the virtual child. /// /// The id. /// BaseItem. /// id public BaseItem FindVirtualChild(Guid id) { if (id == Guid.Empty) { throw new ArgumentNullException("id"); } return _virtualChildren.FirstOrDefault(i => i.Id == id); } } }