File: System\DirectoryServices\ActiveDirectory\ActiveDirectorySubnetCollection.cs
Web Access
Project: src\src\runtime\src\libraries\System.DirectoryServices\src\System.DirectoryServices.csproj (System.DirectoryServices)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections;
using System.Runtime.InteropServices;
using System.Text;

namespace System.DirectoryServices.ActiveDirectory
{
    public class ActiveDirectorySubnetCollection : CollectionBase
    {
        internal readonly Hashtable changeList;
        internal bool initialized;
        private readonly string _siteDN;
        private readonly DirectoryContext _context;
        private readonly ArrayList _copyList = new ArrayList();

        internal ActiveDirectorySubnetCollection(DirectoryContext context, string siteDN)
        {
            _context = context;
            _siteDN = siteDN;

            Hashtable tempTable = new Hashtable();
            changeList = Hashtable.Synchronized(tempTable);
        }

        public ActiveDirectorySubnet this[int index]
        {
            get => (ActiveDirectorySubnet)InnerList[index]!;
            set
            {
                ActiveDirectorySubnet subnet = (ActiveDirectorySubnet)value;

                if (subnet == null)
                    throw new ArgumentNullException(nameof(value));

                if (!subnet.existing)
                    throw new InvalidOperationException(SR.Format(SR.SubnetNotCommitted, subnet.Name));

                if (!Contains(subnet))
                    List[index] = subnet;
                else
                    throw new ArgumentException(SR.Format(SR.AlreadyExistingInCollection, subnet), nameof(value));
            }
        }

        public int Add(ActiveDirectorySubnet subnet)
        {
            if (subnet == null)
                throw new ArgumentNullException(nameof(subnet));

            if (!subnet.existing)
                throw new InvalidOperationException(SR.Format(SR.SubnetNotCommitted, subnet.Name));

            if (!Contains(subnet))
                return List.Add(subnet);
            else
                throw new ArgumentException(SR.Format(SR.AlreadyExistingInCollection, subnet), nameof(subnet));
        }

        public void AddRange(ActiveDirectorySubnet[] subnets)
        {
            if (subnets == null)
                throw new ArgumentNullException(nameof(subnets));

            foreach (ActiveDirectorySubnet s in subnets)
            {
                if (s == null)
                {
                    throw new ArgumentException(null, nameof(subnets));
                }
            }

            for (int i = 0; ((i) < (subnets.Length)); i = ((i) + (1)))
                this.Add(subnets[i]);
        }

        public void AddRange(ActiveDirectorySubnetCollection subnets)
        {
            if (subnets == null)
                throw new ArgumentNullException(nameof(subnets));

            int count = subnets.Count;
            for (int i = 0; i < count; i++)
                this.Add(subnets[i]);
        }

        public bool Contains(ActiveDirectorySubnet subnet)
        {
            if (subnet == null)
                throw new ArgumentNullException(nameof(subnet));

            if (!subnet.existing)
                throw new InvalidOperationException(SR.Format(SR.SubnetNotCommitted, subnet.Name));

            string dn = (string)PropertyManager.GetPropertyValue(subnet.context, subnet.cachedEntry, PropertyManager.DistinguishedName)!;

            for (int i = 0; i < InnerList.Count; i++)
            {
                ActiveDirectorySubnet tmp = (ActiveDirectorySubnet)InnerList[i]!;
                string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName)!;

                if (Utils.Compare(tmpDn, dn) == 0)
                {
                    return true;
                }
            }
            return false;
        }

        public void CopyTo(ActiveDirectorySubnet[] array, int index)
        {
            List.CopyTo(array, index);
        }

        public int IndexOf(ActiveDirectorySubnet subnet)
        {
            if (subnet == null)
                throw new ArgumentNullException(nameof(subnet));

            if (!subnet.existing)
                throw new InvalidOperationException(SR.Format(SR.SubnetNotCommitted, subnet.Name));

            string dn = (string)PropertyManager.GetPropertyValue(subnet.context, subnet.cachedEntry, PropertyManager.DistinguishedName)!;

            for (int i = 0; i < InnerList.Count; i++)
            {
                ActiveDirectorySubnet tmp = (ActiveDirectorySubnet)InnerList[i]!;
                string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName)!;

                if (Utils.Compare(tmpDn, dn) == 0)
                {
                    return i;
                }
            }
            return -1;
        }

        public void Insert(int index, ActiveDirectorySubnet subnet)
        {
            if (subnet == null)
                throw new ArgumentNullException(nameof(subnet));

            if (!subnet.existing)
                throw new InvalidOperationException(SR.Format(SR.SubnetNotCommitted, subnet.Name));

            if (!Contains(subnet))
                List.Insert(index, subnet);
            else
                throw new ArgumentException(SR.Format(SR.AlreadyExistingInCollection, subnet), nameof(subnet));
        }

        public void Remove(ActiveDirectorySubnet subnet)
        {
            if (subnet == null)
                throw new ArgumentNullException(nameof(subnet));

            if (!subnet.existing)
                throw new InvalidOperationException(SR.Format(SR.SubnetNotCommitted, subnet.Name));

            string dn = (string)PropertyManager.GetPropertyValue(subnet.context, subnet.cachedEntry, PropertyManager.DistinguishedName)!;

            for (int i = 0; i < InnerList.Count; i++)
            {
                ActiveDirectorySubnet tmp = (ActiveDirectorySubnet)InnerList[i]!;
                string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName)!;

                if (Utils.Compare(tmpDn, dn) == 0)
                {
                    List.Remove(tmp);
                    return;
                }
            }

            // something that does not exist in the collectio
            throw new ArgumentException(SR.Format(SR.NotFoundInCollection, subnet), nameof(subnet));
        }

        protected override void OnClear()
        {
            if (initialized)
            {
                _copyList.Clear();
                foreach (object o in List)
                {
                    _copyList.Add(o);
                }
            }
        }

        protected override void OnClearComplete()
        {
            // if the property exists, clear it out
            if (initialized)
            {
                for (int i = 0; i < _copyList.Count; i++)
                {
                    OnRemoveComplete(i, _copyList[i]!);
                }
            }
        }

#pragma warning disable CS8765 // Nullability doesn't match overridden member
        protected override void OnInsertComplete(int index, object value)
#pragma warning restore CS8765
        {
            if (initialized)
            {
                ActiveDirectorySubnet subnet = (ActiveDirectorySubnet)value;
                string dn = (string)PropertyManager.GetPropertyValue(subnet.context, subnet.cachedEntry, PropertyManager.DistinguishedName)!;

                try
                {
                    if (changeList.Contains(dn))
                    {
                        ((DirectoryEntry)changeList[dn]!).Properties["siteObject"].Value = _siteDN;
                    }
                    else
                    {
                        DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(_context, MakePath(dn));
                        de.Properties["siteObject"].Value = _siteDN;
                        changeList.Add(dn, de);
                    }
                }
                catch (COMException e)
                {
                    throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
                }
            }
        }

#pragma warning disable CS8765 // Nullability doesn't match overridden member
        protected override void OnRemoveComplete(int index, object value)
#pragma warning restore CS8765
        {
            ActiveDirectorySubnet subnet = (ActiveDirectorySubnet)value;
            string dn = (string)PropertyManager.GetPropertyValue(subnet.context, subnet.cachedEntry, PropertyManager.DistinguishedName)!;

            try
            {
                if (changeList.Contains(dn))
                {
                    ((DirectoryEntry)changeList[dn]!).Properties["siteObject"].Clear();
                }
                else
                {
                    DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(_context, MakePath(dn));
                    de.Properties["siteObject"].Clear();
                    changeList.Add(dn, de);
                }
            }
            catch (COMException e)
            {
                throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
            }
        }

#pragma warning disable CS8765 // Nullability doesn't match overridden member
        protected override void OnSetComplete(int index, object oldValue, object newValue)
#pragma warning restore CS8765
        {
            OnRemoveComplete(index, oldValue);
            OnInsertComplete(index, newValue);
        }

        protected override void OnValidate(object value)
        {
            if (value == null) throw new ArgumentNullException(nameof(value));

            if (!(value is ActiveDirectorySubnet))
                throw new ArgumentException(null, nameof(value));

            if (!((ActiveDirectorySubnet)value).existing)
                throw new InvalidOperationException(SR.Format(SR.SubnetNotCommitted, ((ActiveDirectorySubnet)value).Name));
        }

        private string MakePath(string subnetDN)
        {
            string rdn = Utils.GetRdnFromDN(subnetDN);
            StringBuilder str = new StringBuilder();
            for (int i = 0; i < rdn.Length; i++)
            {
                if (rdn[i] == '/')
                {
                    str.Append('\\');
                }

                str.Append(rdn[i]);
            }

            return str.ToString() + "," + subnetDN.Substring(rdn.Length + 1);
        }
    }
}