using System;
using System.Collections;
namespace Qpid.Collections
{
public class LinkedHashtable : DictionaryBase
{
///
/// Maps from key to LinkedDictionaryEntry
///
private Hashtable _indexedValues = new Hashtable();
private LinkedDictionaryEntry _head;
private LinkedDictionaryEntry _tail;
public class LinkedDictionaryEntry
{
public LinkedDictionaryEntry previous;
public LinkedDictionaryEntry next;
public object key;
public object value;
public LinkedDictionaryEntry(object key, object value)
{
this.key = key;
this.value = value;
}
}
public object this[object index]
{
get
{
return ((LinkedDictionaryEntry)_indexedValues[index]).value;
}
set
{
Dictionary[index] = value;
}
}
protected override void OnInsertComplete(object key, object value)
{
LinkedDictionaryEntry de = new LinkedDictionaryEntry(key, value);
if (_head == null)
{
_head = de;
_tail = de;
}
else
{
_tail.next = de;
de.previous = _tail;
_tail = de;
}
_indexedValues[key] = de;
}
protected override void OnSetComplete(object key, object oldValue, object newValue)
{
if (oldValue == null)
{
OnInsertComplete(key, newValue);
}
}
protected override void OnRemoveComplete(object key, object value)
{
LinkedDictionaryEntry de = (LinkedDictionaryEntry)_indexedValues[key];
LinkedDictionaryEntry prev = de.previous;
if (prev == null)
{
_head = de.next;
}
else
{
prev.next = de.next;
}
LinkedDictionaryEntry next = de.next;
if (next == null)
{
_tail = de;
}
else
{
next.previous = de.previous;
}
}
public ICollection Values
{
get
{
return InnerHashtable.Values;
}
}
public bool Contains(object key)
{
return InnerHashtable.Contains(key);
}
public void Remove(object key)
{
Dictionary.Remove(key);
}
public LinkedDictionaryEntry Head
{
get
{
return _head;
}
}
public LinkedDictionaryEntry Tail
{
get
{
return _tail;
}
}
private class LHTEnumerator : IEnumerator
{
private LinkedHashtable _container;
private LinkedDictionaryEntry _current;
///
/// Set once we have navigated off the end of the collection
///
private bool _needsReset = false;
public LHTEnumerator(LinkedHashtable container)
{
_container = container;
}
public object Current
{
get
{
if (_current == null)
{
throw new Exception("Iterator before first element");
}
else
{
return _current;
}
}
}
public bool MoveNext()
{
if (_needsReset)
{
return false;
}
else if (_current == null)
{
_current = _container.Head;
}
else
{
_current = _current.next;
}
_needsReset = (_current == null);
return !_needsReset;
}
public void Reset()
{
_current = null;
_needsReset = false;
}
}
public new IEnumerator GetEnumerator()
{
return new LHTEnumerator(this);
}
public void MoveToHead(object key)
{
LinkedDictionaryEntry de = (LinkedDictionaryEntry)_indexedValues[key];
if (de == null)
{
throw new ArgumentException("Key " + key + " not found");
}
// if the head is the element then there is nothing to do
if (_head == de)
{
return;
}
de.previous.next = de.next;
if (de.next != null)
{
de.next.previous = de.previous;
}
else
{
_tail = de.previous;
}
de.next = _head;
_head = de;
de.previous = null;
}
}
}