//--------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner Microsoft // @backupOwner Microsoft //--------------------------------------------------------------------- namespace System.Data.EntityModel.SchemaObjectModel { using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Data.Metadata.Edm; using System.Diagnostics; /// /// A collection of RelationshipEnds /// internal sealed class RelationshipEndCollection : IList { private Dictionary _endLookup = null; private List _keysInDefOrder = null; /// /// construct a RelationshipEndCollection /// public RelationshipEndCollection() { } /// /// How many RelationshipEnds are in the collection /// public int Count { get { return KeysInDefOrder.Count; } } /// /// Add a relationship end /// /// the end to add public void Add(IRelationshipEnd end) { Debug.Assert(end != null, "end parameter is null"); SchemaElement endElement = end as SchemaElement; Debug.Assert(endElement != null, "end is not a SchemaElement"); // this should have been caught before this, just ignore it if ( !IsEndValid(end) ) return; if ( !ValidateUniqueName(endElement, end.Name)) return; EndLookup.Add(end.Name,end); KeysInDefOrder.Add(end.Name); } /// /// See if an end can be added to the collection /// /// the end to add /// true if the end is valid, false otherwise private static bool IsEndValid(IRelationshipEnd end) { return !string.IsNullOrEmpty(end.Name); } /// /// /// /// /// /// private bool ValidateUniqueName(SchemaElement end, string name) { if ( EndLookup.ContainsKey(name) ) { end.AddError( ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.EndNameAlreadyDefinedDuplicate(name)); return false; } return true; } /// /// Remove a relationship end /// /// the end to remove /// true if item was in list public bool Remove(IRelationshipEnd end) { Debug.Assert(end != null, "end parameter is null"); if ( !IsEndValid(end) ) return false; KeysInDefOrder.Remove(end.Name); bool wasInList = EndLookup.Remove(end.Name); return wasInList; } /// /// See if a relationship end is in the collection /// /// the name of the end /// true if the end name is in the collection public bool Contains(string name) { return EndLookup.ContainsKey(name); } /// /// See if a relationship end is in the collection /// /// the name of the end /// true if the end is in the collection public bool Contains(IRelationshipEnd end) { Debug.Assert(end != null, "end parameter is null"); return Contains(end.Name); } public IRelationshipEnd this[int index] { get { return EndLookup[KeysInDefOrder[index]]; } set { throw EntityUtil.NotSupported(); } } /// /// get a typed enumerator for the collection /// /// the enumerator public IEnumerator GetEnumerator() { return new Enumerator(EndLookup,KeysInDefOrder); } public bool TryGetEnd( string name, out IRelationshipEnd end ) { return EndLookup.TryGetValue( name, out end ); } /// /// get an un-typed enumerator for the collection /// /// the enumerator IEnumerator System.Collections.IEnumerable.GetEnumerator() { return new Enumerator(EndLookup,KeysInDefOrder); } /// /// The data for the collection /// private Dictionary EndLookup { get { if ( _endLookup == null ) _endLookup = new Dictionary(StringComparer.Ordinal); return _endLookup; } } /// /// the definition order collection /// private List KeysInDefOrder { get { if ( _keysInDefOrder == null ) _keysInDefOrder = new List(); return _keysInDefOrder; } } /// /// remove all elements from the collection /// public void Clear() { EndLookup.Clear(); KeysInDefOrder.Clear(); } /// /// can the collection be modified /// public bool IsReadOnly { get { return false; } } /// /// Not supported /// /// the end /// nothing int IList.IndexOf(IRelationshipEnd end) { throw EntityUtil.NotSupported(); } /// /// Not supported /// /// the index /// the end void IList.Insert(int index, IRelationshipEnd end) { throw EntityUtil.NotSupported(); } /// /// Not supported /// /// the index void IList.RemoveAt(int index) { throw EntityUtil.NotSupported(); } /// /// copy all elements to an array /// /// array to copy to /// The zero-based index in array at which copying begins. public void CopyTo(IRelationshipEnd[] ends, int index ) { Debug.Assert(ends.Length-index >= Count); foreach ( IRelationshipEnd end in this ) ends[index++] = end; } /// /// enumerator for the RelationshipEnd collection /// the ends as traversed in the order in which they were added /// private sealed class Enumerator : IEnumerator { private List.Enumerator _Enumerator; private Dictionary _Data = null; /// /// construct the enumerator /// /// the real data /// the keys to the real data in inserted order public Enumerator(Dictionary data, List keysInDefOrder) { Debug.Assert(data != null); Debug.Assert(keysInDefOrder != null); _Enumerator = keysInDefOrder.GetEnumerator(); _Data = data; } /// /// reset the enumerator /// public void Reset() { // reset is implemented explicitly ((IEnumerator)_Enumerator).Reset(); } /// /// get current relationship end from the enumerator /// public IRelationshipEnd Current { get { return _Data[_Enumerator.Current]; } } /// /// get current relationship end from the enumerator /// object System.Collections.IEnumerator.Current { get { return _Data[_Enumerator.Current]; } } /// /// move to the next element in the collection /// /// true if there is a next, false if not public bool MoveNext() { return _Enumerator.MoveNext(); } /// /// dispose of the enumerator /// public void Dispose() { } } } }