aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/Entities/CollectionFolder.cs
blob: bc50ce61822b257a680e4754b68e96e04629b8bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using System;
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
{
    /// <summary>
    /// 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
    /// </summary>
    public class CollectionFolder : Folder, ICollectionFolder
    {
        /// <summary>
        /// Gets a value indicating whether this instance is virtual folder.
        /// </summary>
        /// <value><c>true</c> if this instance is virtual folder; otherwise, <c>false</c>.</value>
        [IgnoreDataMember]
        public override bool IsVirtualFolder
        {
            get
            {
                return true;
            }
        }

        public string CollectionType { get; set; }

        /// <summary>
        /// Allow different display preferences for each collection folder
        /// </summary>
        /// <value>The display prefs id.</value>
        public override Guid DisplayPreferencesId
        {
            get
            {
                return Id;
            }
        }

        // Cache this since it will be used a lot
        /// <summary>
        /// The null task result
        /// </summary>
        private static readonly Task NullTaskResult = Task.FromResult<object>(null);

        /// <summary>
        /// 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***
        /// </summary>
        /// <param name="progress">The progress.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="recursive">if set to <c>true</c> [recursive].</param>
        /// <param name="forceRefreshMetadata">if set to <c>true</c> [force refresh metadata].</param>
        /// <returns>Task.</returns>
        protected override Task ValidateChildrenInternal(IProgress<double> 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...
            if (IndexCache != null)
            {
                IndexCache.Clear();
            }

            return NullTaskResult;
        }

        private List<LinkedChild> _linkedChildren;
        
        /// <summary>
        /// Our children are actually just references to the ones in the physical root...
        /// </summary>
        /// <value>The linked children.</value>
        public override List<LinkedChild> LinkedChildren
        {
            get { return _linkedChildren ?? (_linkedChildren = GetLinkedChildrenInternal()); }
            set
            {
                base.LinkedChildren = value;
            }
        }
        private List<LinkedChild> GetLinkedChildrenInternal()
        {
            Dictionary<string, string> locationsDicionary;

            try
            {
                locationsDicionary = ResolveArgs.PhysicalLocations.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
            }
            catch (IOException ex)
            {
                Logger.ErrorException("Error getting ResolveArgs for {0}", ex, Path);
                return new List<LinkedChild>();
            }

            return LibraryManager.RootFolder.Children
                .OfType<Folder>()
                .Where(i => i.Path != null && locationsDicionary.ContainsKey(i.Path))
                .SelectMany(c => c.LinkedChildren).ToList();
        }

        private IEnumerable<BaseItem> _actualChildren;

        /// <summary>
        /// Our children are actually just references to the ones in the physical root...
        /// </summary>
        /// <value>The actual children.</value>
        protected override IEnumerable<BaseItem> ActualChildren
        {
            get { return _actualChildren ?? (_actualChildren = GetActualChildren()); }
        }

        private IEnumerable<BaseItem> GetActualChildren()
        {
            Dictionary<string, string> locationsDicionary;

            try
            {
                locationsDicionary = ResolveArgs.PhysicalLocations.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
            }
            catch (IOException ex)
            {
                Logger.ErrorException("Error getting ResolveArgs for {0}", ex, Path);
                return new BaseItem[] { };
            }

            return
                LibraryManager.RootFolder.Children
                .OfType<Folder>()
                .Where(i => i.Path != null && locationsDicionary.ContainsKey(i.Path))
                .SelectMany(c => c.Children);
        }

        public void ResetDynamicChildren()
        {
            _actualChildren = null;
            _linkedChildren = null;
        }
    }
}