//---------------------------------------------------------------------
//
// 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()
{
}
}
}
}