' ***********************************************************************
' Author : ElektroStudios
' Modified : 08-July-2023
' ***********************************************************************
#Region " Option Statements "
Option Strict On
Option Explicit On
Option Infer Off
#End Region
#Region " Imports "
Imports System.Collections.Specialized
Imports System.Runtime.Serialization
#End Region
Namespace DevCase.Runtime.Collections
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Similarly to a <see cref="NameValueCollection"/>, this class represents a
''' collection of associated <see cref="String"/> keys and <see cref="Object"/> values
''' that can be accessed either with the name or with the index.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<Serializable>
Public Class NameObjectCollection : Inherits NameObjectCollectionBase
#Region " Private MethFieldsods "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Cached array of values in this <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Private _all() As Object
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Cached array of keys in this <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Private _allKeys() As String
#End Region
#Region " Properties "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets or sets the entry with the specified key in this <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="name">
''' The <see cref="String"/> key of the entry to locate. The key can be null.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="Object"/> that contains the comma-separated list of values associated with
''' the specified key, if found; otherwise, null.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Default Public Property Item(name As String) As Object
Get
Return Me.[Get](name)
End Get
Set(value As Object)
Me.[Set](name, value)
End Set
End Property
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the entry at the specified index of this <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="index">
''' The zero-based index of the entry to locate in the collection.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="Object"/> that contains the comma-separated list of values at the specified
''' index of the collection.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Default Public ReadOnly Property Item(index As Integer) As Object
Get
Return Me.[Get](index)
End Get
End Property
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets all the keys in this <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="String"/> array that contains all the keys of this <see cref="NameObjectCollection"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Overridable ReadOnly Property AllKeys() As String()
Get
If Me._allKeys Is Nothing Then
Me._allKeys = Me.BaseGetAllKeys()
End If
Return Me._allKeys
End Get
End Property
#End Region
#Region " Constructors "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Initializes a new instance of the <see cref="NameObjectCollection"/>
''' class that is empty, has the default initial capacity and uses the default case-insensitive
''' hash code provider and the default case-insensitive comparer.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Public Sub New()
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Initializes a new instance of the <see cref="NameObjectCollection"/>
''' class that is empty, has the specified initial capacity and uses the specified
''' hash code provider and the specified comparer.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="hashProvider">
''' The <see cref="System.Collections.IHashCodeProvider"/> that will supply the hash codes for
''' all keys in this <see cref="NameObjectCollection"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <param name="comparer">
''' The <see cref="System.Collections.IComparer"/> to use to determine whether two keys are equal.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<Obsolete("Please use NameObjectCollection(IEqualityComparer) instead.")>
Public Sub New(hashProvider As IHashCodeProvider, comparer As IComparer)
MyBase.New(hashProvider, comparer)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Initializes a new instance of the <see cref="NameObjectCollection"/>
''' class that is empty, has the specified initial capacity and uses the default
''' case-insensitive hash code provider and the default case-insensitive comparer.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="capacity">
''' The initial number of entries that this <see cref="NameObjectCollection"/>
''' can contain.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Public Sub New(capacity As Integer)
MyBase.New(capacity)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Initializes a new instance of the <see cref="NameObjectCollection"/>
''' class that is empty, has the default initial capacity, and uses the specified
''' <see cref="System.Collections.IEqualityComparer"/> object.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="equalityComparer">
''' The <see cref="System.Collections.IEqualityComparer"/> object to use to determine whether two
''' keys are equal and to generate hash codes for the keys in the collection.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Public Sub New(equalityComparer As IEqualityComparer)
MyBase.New(equalityComparer)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Initializes a new instance of the <see cref="NameObjectCollection"/>
''' class that is empty, has the specified initial capacity, and uses the specified
''' <see cref="System.Collections.IEqualityComparer"/> object.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="capacity">
''' The initial number of entries that this <see cref="NameObjectCollection"/>
''' object can contain.
''' </param>
'''
''' <param name="equalityComparer">
''' The <see cref="System.Collections.IEqualityComparer"/> object to use to determine whether two
''' keys are equal and to generate hash codes for the keys in the collection.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Public Sub New(capacity As Integer, equalityComparer As IEqualityComparer)
MyBase.New(capacity, equalityComparer)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Copies the entries from the specified <see cref="NameObjectCollection"/>
''' to a new <see cref="NameObjectCollection"/> with the specified
''' initial capacity or the same initial capacity as the number of entries copied,
''' whichever is greater, and using the default case-insensitive hash code provider
''' and the default case-insensitive comparer.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="capacity">
''' The initial number of entries that this <see cref="NameObjectCollection"/>
''' can contain.
''' </param>
'''
''' <param name="col">
''' this <see cref="NameObjectCollection"/> to copy to the new <see cref="NameObjectCollection"/>
''' instance.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Public Sub New(capacity As Integer, col As NameObjectCollection)
MyBase.New(capacity)
If col Is Nothing Then
Throw New ArgumentNullException(NameOf(col))
End If
Me.Add(col)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Initializes a new instance of the <see cref="NameObjectCollection"/>
''' class that is empty, has the specified initial capacity and uses the specified
''' hash code provider and the specified comparer.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="capacity">
''' The initial number of entries that this <see cref="NameObjectCollection"/>
''' can contain.
''' </param>
'''
''' <param name="hashProvider">
''' The <see cref="System.Collections.IHashCodeProvider"/> that will supply the hash codes for
''' all keys in this <see cref="NameObjectCollection"/>.
''' </param>
'''
''' <param name="comparer">
''' The <see cref="System.Collections.IComparer"/> to use to determine whether two keys are equal.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<Obsolete("Please use NameObjectCollection(Int32, IEqualityComparer) instead.")>
Public Sub New(capacity As Integer, hashProvider As IHashCodeProvider, comparer As IComparer)
MyBase.New(capacity, hashProvider, comparer)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Initializes a new instance of the <see cref="NameObjectCollection"/>
''' class that is serializable and uses the specified <see cref="System.Runtime.Serialization.SerializationInfo"/>
''' and <see cref="System.Runtime.Serialization.StreamingContext"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="info">
''' A <see cref="System.Runtime.Serialization.SerializationInfo"/> object that contains the information
''' required to serialize the new <see cref="NameObjectCollection"/>
''' instance.
''' </param>
'''
''' <param name="context">
''' A <see cref="System.Runtime.Serialization.StreamingContext"/> object that contains the source
''' and destination of the serialized stream associated with the new <see cref="NameObjectCollection"/>
''' instance.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Protected Sub New(info As SerializationInfo, context As StreamingContext)
MyBase.New(info, context)
End Sub
#End Region
#Region " Public Methods "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Copies the entries in the specified <see cref="NameObjectCollection"/>
''' to the current <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="c">
''' this <see cref="NameObjectCollection"/> to copy to the current
''' <see cref="NameObjectCollection"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Public Sub Add(c As NameObjectCollection)
If c Is Nothing Then
Throw New ArgumentNullException(NameOf(c))
End If
Me.InvalidateCachedArrays()
Dim count As Integer = c.Count
For i As Integer = 0 To count - 1
Dim key As String = c.GetKey(i)
Dim values() As Object = c.GetValues(i)
If values IsNot Nothing Then
For j As Integer = 0 To values.Length - 1
Me.Add(key, values(j))
Next j
Else
Me.Add(key, Nothing)
End If
Next i
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Invalidates the cached arrays and removes all entries from this <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Public Overridable Sub Clear()
If MyBase.IsReadOnly Then
Throw New NotSupportedException("CollectionReadOnly")
End If
Me.InvalidateCachedArrays()
MyBase.BaseClear()
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Copies the entire <see cref="NameObjectCollection"/> to a compatible
''' one-dimensional <see cref="System.Array"/>, starting at the specified index of the target array.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="dest">
''' The one-dimensional <see cref="System.Array"/> that is the destination of the elements copied
''' from <see cref="NameObjectCollection"/>. The <see cref="System.Array"/> must
''' have zero-based indexing.
''' </param>
'''
''' <param name="index">
''' The zero-based index in dest at which copying begins.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Public Sub CopyTo(dest As System.Array, index As Integer)
If dest Is Nothing Then
Throw New ArgumentNullException(NameOf(dest))
End If
If dest.Rank <> 1 Then
Throw New ArgumentException("Arg_MultiRank")
End If
If index < 0 Then
Throw New ArgumentOutOfRangeException(NameOf(index), "IndexOutOfRange")
End If
Dim count As Integer = Me.Count
If dest.Length - index < count Then
Throw New ArgumentException("Arg_InsufficientSpace")
End If
If Me._all Is Nothing Then
Dim array(count - 1) As Object
For i As Integer = 0 To count - 1
array(i) = Me.[Get](i)
dest.SetValue(array(i), i + index)
Next i
Me._all = array
Else
For j As Integer = 0 To count - 1
dest.SetValue(_all(j), j + index)
Next j
End If
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets a value indicating whether this <see cref="NameObjectCollection"/>
''' contains keys that are not null.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' true if this <see cref="NameObjectCollection"/> contains keys
''' that are not null; otherwise, false.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Function HasKeys() As Boolean
Return Me.InternalHasKeys()
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Adds an entry with the specified name and value to this <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="name">
''' The <see cref="String"/> key of the entry to add. The key can be null.
''' </param>
'''
''' <param name="value">
''' The <see cref="String"/> value of the entry to add. The value can be null.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Public Overridable Sub Add(name As String, value As Object)
If MyBase.IsReadOnly Then
Throw New NotSupportedException("CollectionReadOnly")
End If
Me.InvalidateCachedArrays()
Dim arrayList As ArrayList = DirectCast(MyBase.BaseGet(name), ArrayList)
If arrayList Is Nothing Then
arrayList = New ArrayList(1)
If value IsNot Nothing Then
arrayList.Add(value)
End If
MyBase.BaseAdd(name, arrayList)
ElseIf value IsNot Nothing Then
arrayList.Add(value)
End If
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the values associated with the specified key from this <see cref="NameObjectCollection"/>
''' combined into one comma-separated list.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="name">
''' The <see cref="String"/> key of the entry that contains the values to get. The key can
''' be null.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="String"/> that contains a comma-separated list of the values associated
''' with the specified key from this <see cref="NameObjectCollection"/>,
''' if found; otherwise, null.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Overridable Function [Get](name As String) As Object
Dim list As ArrayList = DirectCast(MyBase.BaseGet(name), ArrayList)
Return NameObjectCollection.GetAsOneObject(list)
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the values associated with the specified key from this <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="name">
''' The <see cref="String"/> key of the entry that contains the values to get. The key can
''' be null.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="Object"/> array that contains the values associated with the specified
''' key from this <see cref="NameObjectCollection"/>, if found; otherwise,
''' null.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Overridable Function GetValues(name As String) As Object()
Dim list As ArrayList = DirectCast(MyBase.BaseGet(name), ArrayList)
Return NameObjectCollection.GetAsObjectArray(list)
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Sets the value of an entry in this <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="name">
''' The <see cref="String"/> key of the entry to add the new value to. The key can be null.
''' </param>
'''
''' <param name="value">
''' The <see cref="Object"/> that represents the new value to add to the specified entry.
''' The value can be null.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Public Overridable Sub [Set](name As String, value As Object)
If MyBase.IsReadOnly Then
Throw New NotSupportedException("CollectionReadOnly")
End If
Me.InvalidateCachedArrays()
Dim arrayList As New ArrayList(1) From {value}
MyBase.BaseSet(name, arrayList)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Removes the entries with the specified key from this <see cref="NameObjectCollection"/>
''' instance.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="name">
''' The <see cref="String"/> key of the entry to remove. The key can be null.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Public Overridable Sub Remove(name As String)
Me.InvalidateCachedArrays()
MyBase.BaseRemove(name)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the values at the specified index of this <see cref="NameObjectCollection"/>
''' combined into one comma-separated list.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="index">
''' The zero-based index of the entry that contains the values to get from the collection.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="String"/> that contains a comma-separated list of the values at the specified
''' index of this <see cref="NameObjectCollection"/>, if found; otherwise,
''' null.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Overridable Function [Get](index As Integer) As Object
Dim list As ArrayList = DirectCast(MyBase.BaseGet(index), ArrayList)
Return NameObjectCollection.GetAsOneObject(list)
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the values at the specified index of this <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="index">
''' The zero-based index of the entry that contains the values to get from the collection.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="String"/> array that contains the values at the specified index of the
''' <see cref="NameObjectCollection"/>, if found; otherwise, null.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Overridable Function GetValues(index As Integer) As Object()
Dim list As ArrayList = DirectCast(MyBase.BaseGet(index), ArrayList)
Return NameObjectCollection.GetAsObjectArray(list)
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the key at the specified index of this <see cref="NameObjectCollection"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="index">
''' The zero-based index of the key to get from the collection.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="String"/> that contains the key at the specified index of this <see cref="NameObjectCollection"/>,
''' if found; otherwise, null.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Overridable Function GetKey(index As Integer) As String
Return MyBase.BaseGetKey(index)
End Function
#End Region
#Region " Private Methods "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Resets the cached arrays of the collection to null.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Protected Sub InvalidateCachedArrays()
Me._all = Nothing
Me._allKeys = Nothing
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets a value indicating whether the <see cref="NameObjectCollection"/> has keys that are not null.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <c>true</c> if the <see cref="NameObjectCollection"/> has keys that are not null; otherwise, <c>false</c>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Friend Overridable Function InternalHasKeys() As Boolean
Return MyBase.BaseHasKeys()
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Converts an <see cref="ArrayList"/> to a single object.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="list">
''' The <see cref="ArrayList"/> to convert.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The converted object. If the <see cref="ArrayList"/> contains a single item, that item is returned.
''' If the <see cref="ArrayList"/> contains multiple items,
''' a <see cref="Collection"/> object is created with the items and returned.
''' If the <see cref="ArrayList"/> is empty or null, null is returned.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Private Shared Function GetAsOneObject(list As ArrayList) As Object
Dim num As Integer = If(list?.Count, 0)
If num = 1 Then
Return list(0)
End If
If num > 1 Then
For i As Integer = 1 To num - 1
Next i
End If
Return Nothing
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Converts an <see cref="ArrayList"/> to an array of objects.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="list">
''' The <see cref="ArrayList"/> to convert.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' An array of objects containing the items from the <see cref="ArrayList"/>.
''' If the <see cref="ArrayList"/> is empty or null, null is returned.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Private Shared Function GetAsObjectArray(list As ArrayList) As Object()
Dim num As Integer = If(list?.Count, 0)
If num = 0 Then
Return Nothing
End If
Dim array(num - 1) As Object
list.CopyTo(0, array, 0, num)
Return array
End Function
#End Region
End Class
End Namespace