|
//---------------------------------------------------------------------
// <copyright file="RelationshipEndCollection.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @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;
/// <summary>
/// A collection of RelationshipEnds
/// </summary>
internal sealed class RelationshipEndCollection : IList<IRelationshipEnd>
{
private Dictionary<string,IRelationshipEnd> _endLookup = null;
private List<string> _keysInDefOrder = null;
/// <summary>
/// construct a RelationshipEndCollection
/// </summary>
public RelationshipEndCollection()
{
}
/// <summary>
/// How many RelationshipEnds are in the collection
/// </summary>
public int Count
{
get
{
return KeysInDefOrder.Count;
}
}
/// <summary>
/// Add a relationship end
/// </summary>
/// <param name="end">the end to add</param>
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);
}
/// <summary>
/// See if an end can be added to the collection
/// </summary>
/// <param name="end">the end to add</param>
/// <returns>true if the end is valid, false otherwise</returns>
private static bool IsEndValid(IRelationshipEnd end)
{
return !string.IsNullOrEmpty(end.Name);
}
/// <summary>
///
/// </summary>
/// <param name="end"></param>
/// <param name="name"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Remove a relationship end
/// </summary>
/// <param name="end">the end to remove</param>
/// <returns>true if item was in list</returns>
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;
}
/// <summary>
/// See if a relationship end is in the collection
/// </summary>
/// <param name="name">the name of the end</param>
/// <returns>true if the end name is in the collection</returns>
public bool Contains(string name)
{
return EndLookup.ContainsKey(name);
}
/// <summary>
/// See if a relationship end is in the collection
/// </summary>
/// <param name="end">the name of the end</param>
/// <returns>true if the end is in the collection</returns>
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();
}
}
/// <summary>
/// get a typed enumerator for the collection
/// </summary>
/// <returns>the enumerator</returns>
public IEnumerator<IRelationshipEnd> GetEnumerator()
{
return new Enumerator(EndLookup,KeysInDefOrder);
}
public bool TryGetEnd( string name, out IRelationshipEnd end )
{
return EndLookup.TryGetValue( name, out end );
}
/// <summary>
/// get an un-typed enumerator for the collection
/// </summary>
/// <returns>the enumerator</returns>
IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new Enumerator(EndLookup,KeysInDefOrder);
}
/// <summary>
/// The data for the collection
/// </summary>
private Dictionary<string,IRelationshipEnd> EndLookup
{
get
{
if ( _endLookup == null )
_endLookup = new Dictionary<string, IRelationshipEnd>(StringComparer.Ordinal);
return _endLookup;
}
}
/// <summary>
/// the definition order collection
/// </summary>
private List<string> KeysInDefOrder
{
get
{
if ( _keysInDefOrder == null )
_keysInDefOrder = new List<string>();
return _keysInDefOrder;
}
}
/// <summary>
/// remove all elements from the collection
/// </summary>
public void Clear()
{
EndLookup.Clear();
KeysInDefOrder.Clear();
}
/// <summary>
/// can the collection be modified
/// </summary>
public bool IsReadOnly
{
get
{
return false;
}
}
/// <summary>
/// Not supported
/// </summary>
/// <param name="end">the end</param>
/// <returns>nothing</returns>
int IList<IRelationshipEnd>.IndexOf(IRelationshipEnd end)
{
throw EntityUtil.NotSupported();
}
/// <summary>
/// Not supported
/// </summary>
/// <param name="index">the index</param>
/// <param name="end">the end</param>
void IList<IRelationshipEnd>.Insert(int index, IRelationshipEnd end)
{
throw EntityUtil.NotSupported();
}
/// <summary>
/// Not supported
/// </summary>
/// <param name="index">the index</param>
void IList<IRelationshipEnd>.RemoveAt(int index)
{
throw EntityUtil.NotSupported();
}
/// <summary>
/// copy all elements to an array
/// </summary>
/// <param name="ends">array to copy to</param>
/// <param name="index">The zero-based index in array at which copying begins.</param>
public void CopyTo(IRelationshipEnd[] ends, int index )
{
Debug.Assert(ends.Length-index >= Count);
foreach ( IRelationshipEnd end in this )
ends[index++] = end;
}
/// <summary>
/// enumerator for the RelationshipEnd collection
/// the ends as traversed in the order in which they were added
/// </summary>
private sealed class Enumerator : IEnumerator<IRelationshipEnd>
{
private List<string>.Enumerator _Enumerator;
private Dictionary<string,IRelationshipEnd> _Data = null;
/// <summary>
/// construct the enumerator
/// </summary>
/// <param name="data">the real data</param>
/// <param name="keysInDefOrder">the keys to the real data in inserted order</param>
public Enumerator(Dictionary<string, IRelationshipEnd> data, List<string> keysInDefOrder)
{
Debug.Assert(data != null);
Debug.Assert(keysInDefOrder != null);
_Enumerator = keysInDefOrder.GetEnumerator();
_Data = data;
}
/// <summary>
/// reset the enumerator
/// </summary>
public void Reset()
{
// reset is implemented explicitly
((IEnumerator)_Enumerator).Reset();
}
/// <summary>
/// get current relationship end from the enumerator
/// </summary>
public IRelationshipEnd Current
{
get
{
return _Data[_Enumerator.Current];
}
}
/// <summary>
/// get current relationship end from the enumerator
/// </summary>
object System.Collections.IEnumerator.Current
{
get
{
return _Data[_Enumerator.Current];
}
}
/// <summary>
/// move to the next element in the collection
/// </summary>
/// <returns>true if there is a next, false if not</returns>
public bool MoveNext()
{
return _Enumerator.MoveNext();
}
/// <summary>
/// dispose of the enumerator
/// </summary>
public void Dispose()
{
}
}
}
}
|