File: System\Data\RelatedView.cs
Web Access
Project: src\src\libraries\System.Data.Common\src\System.Data.Common.csproj (System.Data.Common)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
 
namespace System.Data
{
    internal sealed class RelatedView : DataView, IFilter
    {
        private readonly DataKey? _parentKey;
        private readonly DataKey _childKey;
        private readonly DataRowView? _parentRowView;
        private readonly object[]? _filterValues;
 
        public RelatedView(DataColumn[] columns, object[] values) : base(columns[0].Table, false)
        {
            if (values == null)
            {
                throw ExceptionBuilder.ArgumentNull(nameof(values));
            }
 
            _parentRowView = null;
            _parentKey = null;
            _childKey = new DataKey(columns, true);
            _filterValues = values;
            Debug.Assert(Table == _childKey.Table, "Key.Table Must be equal to Current Table");
            base.ResetRowViewCache();
        }
 
        public RelatedView(DataRowView parentRowView, DataKey parentKey, DataColumn[] childKeyColumns) : base(childKeyColumns[0].Table, false)
        {
            _filterValues = null;
            _parentRowView = parentRowView;
            _parentKey = parentKey;
            _childKey = new DataKey(childKeyColumns, true);
            Debug.Assert(Table == _childKey.Table, "Key.Table Must be equal to Current Table");
            base.ResetRowViewCache();
        }
 
        private object[]? GetParentValues()
        {
            if (_filterValues != null)
            {
                return _filterValues;
            }
 
            if (!_parentRowView!.HasRecord())
            {
                return null;
            }
            return _parentKey!.Value.GetKeyValues(_parentRowView.GetRecord());
        }
 
 
        public bool Invoke(DataRow row, DataRowVersion version)
        {
            object[]? parentValues = GetParentValues();
            if (parentValues == null)
            {
                return false;
            }
 
            object[] childValues = row.GetKeyValues(_childKey, version);
 
            bool allow = childValues.AsSpan().SequenceEqual(parentValues);
 
            IFilter? baseFilter = base.GetFilter();
            if (baseFilter != null)
            {
                allow &= baseFilter.Invoke(row, version);
            }
 
            return allow;
        }
 
        internal override IFilter GetFilter() => this;
 
        // move to OnModeChanged
        public override DataRowView AddNew()
        {
            DataRowView addNewRowView = base.AddNew();
            addNewRowView.Row.SetKeyValues(_childKey, GetParentValues()!);
            return addNewRowView;
        }
 
        internal override void SetIndex(string newSort, DataViewRowState newRowStates, IFilter? newRowFilter)
        {
            SetIndex2(newSort, newRowStates, newRowFilter, false);
            Reset();
        }
 
        public override bool Equals([NotNullWhen(true)] DataView? dv)
        {
            RelatedView? other = dv as RelatedView;
            if (other == null)
            {
                return false;
            }
            if (!base.Equals(dv))
            {
                return false;
            }
            if (_filterValues != null)
            {
                return (CompareArray(_childKey.ColumnsReference, other._childKey.ColumnsReference) && CompareArray(_filterValues, other._filterValues));
            }
            else
            {
                if (other._filterValues != null)
                {
                    return false;
                }
 
                return (CompareArray(_childKey.ColumnsReference, other._childKey.ColumnsReference) &&
                        CompareArray(_parentKey!.Value.ColumnsReference, _parentKey.Value.ColumnsReference) &&
                        _parentRowView!.Equals(other._parentRowView));
            }
        }
 
        private static bool CompareArray(object?[]? value1, object?[]? value2)
        {
            if (value1 == null || value2 == null)
            {
                return value1 == value2;
            }
            if (value1.Length != value2.Length)
            {
                return false;
            }
            for (int i = 0; i < value1.Length; i++)
            {
                if (value1[i] != value2[i])
                    return false;
            }
            return true;
        }
    }
}