RaspberryIO/Unosquare.Swan/Networking/Ldap/LdapSearchResults.cs
2019-12-03 18:44:25 +01:00

87 lines
3.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
namespace Unosquare.Swan.Networking.Ldap {
/// <summary>
/// An LdapSearchResults object is returned from a synchronous search
/// operation. It provides access to all results received during the
/// operation (entries and exceptions).
/// </summary>
/// <seealso cref="LdapConnection.Search"></seealso>
public sealed class LdapSearchResults {
private readonly List<RfcLdapMessage> _messages;
private readonly Int32 _messageId;
/// <summary>
/// Initializes a new instance of the <see cref="LdapSearchResults" /> class.
/// </summary>
/// <param name="messages">The messages.</param>
/// <param name="messageId">The message identifier.</param>
internal LdapSearchResults(List<RfcLdapMessage> messages, Int32 messageId) {
this._messages = messages;
this._messageId = messageId;
}
/// <summary>
/// Returns a count of the items in the search result.
/// Returns a count of the entries and exceptions remaining in the object.
/// If the search was submitted with a batch size greater than zero,
/// getCount reports the number of results received so far but not enumerated
/// with next(). If batch size equals zero, getCount reports the number of
/// items received, since the application thread blocks until all results are
/// received.
/// </summary>
/// <value>
/// The count.
/// </value>
public Int32 Count => new List<RfcLdapMessage>(this._messages)
.Count(x => x.MessageId == this._messageId && GetResponse(x) is LdapSearchResult);
/// <summary>
/// Reports if there are more search results.
/// </summary>
/// <returns>
/// true if there are more search results.
/// </returns>
public Boolean HasMore() => new List<RfcLdapMessage>(this._messages)
.Any(x => x.MessageId == this._messageId && GetResponse(x) is LdapSearchResult);
/// <summary>
/// Returns the next result as an LdapEntry.
/// If automatic referral following is disabled or if a referral
/// was not followed, next() will throw an LdapReferralException
/// when the referral is received.
/// </summary>
/// <returns>
/// The next search result as an LdapEntry.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">Next - No more results.</exception>
public LdapEntry Next() {
IEnumerable<RfcLdapMessage> list = new List<RfcLdapMessage>(this._messages)
.Where(x => x.MessageId == this._messageId);
foreach(RfcLdapMessage item in list) {
_ = this._messages.Remove(item);
LdapMessage response = GetResponse(item);
if(response is LdapSearchResult result) {
return result.Entry;
}
}
throw new ArgumentOutOfRangeException(nameof(Next), "No more results");
}
private static LdapMessage GetResponse(RfcLdapMessage item) {
switch(item.Type) {
case LdapOperation.SearchResponse:
return new LdapSearchResult(item);
case LdapOperation.SearchResultReference:
return new LdapSearchResultReference(item);
default:
return new LdapResponse(item);
}
}
}
}