1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System;
6 using System.Collections;
7 using System.Collections.Generic;
8 using System.Diagnostics;
9 
10 namespace System.IO.Packaging
11 {
12     /// <summary>
13     /// Collection of all the relationships corresponding to a given source PackagePart.
14     /// This class is part of the MMCF Packaging Layer. It handles serialization to/from
15     /// relationship parts, creation of those parts and offers methods to create, delete
16     /// and enumerate relationships.
17     /// </summary>
18     public class PackageRelationshipCollection : IEnumerable<PackageRelationship>
19     {
20         #region IEnumerable
21 
22         /// <summary>
23         /// Returns an enumerator for all the relationships for a PackagePart
24         /// </summary>
25         /// <returns></returns>
IEnumerable.GetEnumerator()26         IEnumerator IEnumerable.GetEnumerator()
27         {
28             return GetEnumerator();
29         }
30 
31 
32         /// <summary>
33         /// Returns an enumerator over all the relationships for a PackagePart
34         /// </summary>
35         /// <returns></returns>
GetEnumerator()36         public IEnumerator<PackageRelationship> GetEnumerator()
37         {
38             List<PackageRelationship>.Enumerator relationshipsEnumerator = _relationships.GetEnumerator();
39 
40             if (_filter == null)
41                 return relationshipsEnumerator;
42             else
43                 return new FilteredEnumerator(relationshipsEnumerator, _filter);
44         }
45         #endregion
46 
47         #region Internal Members
48         /// <summary>
49         /// Constructor
50         /// </summary>
51         /// <remarks>For use by PackagePart</remarks>
PackageRelationshipCollection(InternalRelationshipCollection relationships, string filter)52         internal PackageRelationshipCollection(InternalRelationshipCollection relationships, string filter)
53         {
54             Debug.Assert(relationships != null, "relationships parameter cannot be null");
55 
56             _relationships = relationships;
57             _filter = filter;
58         }
59 
60         #endregion
61 
62         #region Private Members
63 
64         private InternalRelationshipCollection _relationships;
65         private string _filter;
66 
67         #endregion
68 
69         #region Private Class
70 
71         #region FilteredEnumerator Class
72 
73         /// <summary>
74         /// Internal class for the FilteredEnumerator
75         /// </summary>
76         private sealed class FilteredEnumerator : IEnumerator<PackageRelationship>
77         {
78             #region Constructor
79 
80             /// <summary>
81             /// Constructs a FilteredEnumerator
82             /// </summary>
83             /// <param name="enumerator"></param>
84             /// <param name="filter"></param>
FilteredEnumerator(IEnumerator<PackageRelationship> enumerator, string filter)85             internal FilteredEnumerator(IEnumerator<PackageRelationship> enumerator, string filter)
86             {
87                 Debug.Assert((enumerator != null), "Enumerator cannot be null");
88                 Debug.Assert(filter != null, "PackageRelationship filter string cannot be null");
89 
90                 // Look for empty string or string with just spaces
91                 Debug.Assert(filter.Trim() != String.Empty,
92                     "RelationshipType filter cannot be empty string or a string with just spaces");
93 
94                 _enumerator = enumerator;
95                 _filter = filter;
96             }
97 
98             #endregion Constructor
99 
100             #region IEnumerator Methods
101 
102             /// <summary>
103             /// This method keeps moving the enumerator the next position till
104             /// a relationship is found with the matching Name
105             /// </summary>
106             /// <returns>Bool indicating if the enumerator successfully moved to the next position</returns>
IEnumerator.MoveNext()107             bool IEnumerator.MoveNext()
108             {
109                 while (_enumerator.MoveNext())
110                 {
111                     if (RelationshipTypeMatches())
112                         return true;
113                 }
114 
115                 return false;
116             }
117 
118             /// <summary>
119             /// Gets the current object in the enumerator
120             /// </summary>
121             /// <value></value>
122             Object IEnumerator.Current
123             {
124                 get
125                 {
126                     return _enumerator.Current;
127                 }
128             }
129 
130             /// <summary>
131             /// Resets the enumerator to the beginning
132             /// </summary>
IEnumerator.Reset()133             void IEnumerator.Reset()
134             {
135                 _enumerator.Reset();
136             }
137 
138             #endregion IEnumerator Methods
139 
140             #region IEnumerator<PackageRelationship> Members
141 
142 
143             /// <summary>
144             /// Gets the current object in the enumerator
145             /// </summary>
146             /// <value></value>
147             public PackageRelationship Current
148             {
149                 get
150                 {
151                     return _enumerator.Current;
152                 }
153             }
154 
155             #endregion IEnumerator<PackageRelationship> Members
156 
157             #region IDisposable Members
158 
Dispose()159             public void Dispose()
160             {
161                 //Most enumerators have dispose as a no-op, we follow the same pattern.
162                 _enumerator.Dispose();
163             }
164 
165             #endregion IDisposable Members
166 
167             #region Private Methods
168 
RelationshipTypeMatches()169             private bool RelationshipTypeMatches()
170             {
171                 PackageRelationship r = _enumerator.Current;
172 
173                 //Case-sensitive comparison
174                 if (String.CompareOrdinal(r.RelationshipType, _filter) == 0)
175                     return true;
176                 else
177                     return false;
178             }
179 
180             #endregion Private Methods
181 
182             #region Private Members
183 
184             private IEnumerator<PackageRelationship> _enumerator;
185             private string _filter;
186 
187             #endregion Private Members
188         }
189 
190         #endregion FilteredEnumerator Class
191 
192         #endregion Private Class
193     }
194 }
195