using System; using System.Collections.Generic; using System.Text; namespace ScrewTurn.Wiki.SearchEngine { /// /// Implements a IDocument-SortedBasicWordInfo dictionary which treats IDocuments as value type. /// /// All instance members are not thread-safe. public class OccurrenceDictionary : IDictionary { private Dictionary dictionary; private Dictionary mappings; // Used for performance purposes /// /// Initializes a new instance of the class. /// /// The initial capacity of the dictionary. /// If is less than or equal to zero. public OccurrenceDictionary(int capacity) { if(capacity < 0) throw new ArgumentOutOfRangeException("capacity", "Capacity must be greater than zero"); mappings = new Dictionary(capacity); dictionary = new Dictionary(capacity); } /// /// Initializes a new instance of the class. /// public OccurrenceDictionary() : this(10) { } /// /// Gets the number of elements in the dictionary. /// public int Count { get { return dictionary.Count; } } /// /// Adds the specified key and value to the dictionary. /// /// The key of the element to add. /// The value of the element to add. /// If or are null. /// If is already present in the dictionary. public void Add(IDocument key, SortedBasicWordInfoSet value) { if(key == null) throw new ArgumentNullException("key"); if(value == null) throw new ArgumentNullException("value"); if(ContainsKey(key)) throw new ArgumentException("The specified key is already contained in the dictionary", "key"); mappings.Add(key.Name, key); dictionary.Add(key, value); } /// /// Adds the specified key-value pair to the dictionary. /// /// The key-value pair to add. public void Add(KeyValuePair item) { Add(item.Key, item.Value); } /// /// Determines whether the dictionary contains the specified key. /// /// The key to locate. /// true if the dictionary contains the specified key, false otherwise. /// If is null. public bool ContainsKey(IDocument key) { if(key == null) throw new ArgumentNullException("key"); return FindKey(key) != null; } /// /// Gets the keys of the dictionary. /// public ICollection Keys { get { return dictionary.Keys; } } /// /// Removes an element from the dictionary. /// /// The key of the element to remove. /// true if the element is removed, false otherwise. /// If is null. public bool Remove(IDocument key) { if(key == null) throw new ArgumentNullException("key"); try { // The removal is considered to be successful even if no word mappings are removed RemoveExtended(key, uint.MaxValue); return true; } catch(KeyNotFoundException) { return false; } } /// /// Removes an element from the dictionary. /// /// The element to remove. /// true if the element is removed, false otherwise. public bool Remove(KeyValuePair item) { return Remove(item.Key); } /// /// Removes an element from the dictionary. /// /// The key of the element to remove. /// The unique ID of the word that is being removed. /// The list of removed words mappings, in dumpable format. /// If key is not found, a is thrown. /// If is null. /// If is not present in the dictionary. public List RemoveExtended(IDocument key, uint wordId) { if(key == null) throw new ArgumentNullException("key"); IDocument target = FindKey(key); if(target == null) throw new KeyNotFoundException("Specified IDocument was not found"); else { IDocument mappedDoc = mappings[key.Name]; if(mappings.Remove(target.Name)) { // Prepare the list of DumpedWordMapping objects SortedBasicWordInfoSet set = dictionary[mappedDoc]; List dump = new List(set.Count); foreach(BasicWordInfo w in set) { dump.Add(new DumpedWordMapping(wordId, key.ID, w)); } if(!dictionary.Remove(target)) throw new InvalidOperationException("Internal data is broken"); return dump; } else throw new InvalidOperationException("Internal data is broken"); } } /// /// Finds an actual key in the mappings dictionary. /// /// The document. /// The key, or null. /// If is null. private IDocument FindKey(IDocument key) { if(key == null) throw new ArgumentNullException("key"); IDocument target = null; if(mappings.TryGetValue(key.Name, out target)) return target; else return null; } /// /// Tries to retrieve a value from the dictionary. /// /// The key of the value to retrieve. /// The resulting value, or null. /// true if the value is retrieved, false otherwise. /// If is null. public bool TryGetValue(IDocument key, out SortedBasicWordInfoSet value) { if(key == null) throw new ArgumentNullException("key"); IDocument target = FindKey(key); if(target == null) { value = null; return false; } else { value = dictionary[target]; return true; } } /// /// Gets the values of the dictionary. /// public ICollection Values { get { return dictionary.Values; } } /// /// Gets or sets a value in the dictionary. /// /// The key of the value to ger or set. /// The value. /// If is null. /// If the key is not found. public SortedBasicWordInfoSet this[IDocument key] { get { if(key == null) throw new ArgumentNullException("key"); IDocument target = FindKey(key); if(target == null) throw new IndexOutOfRangeException("The specified key was not found"); else return dictionary[target]; } set { if(key == null) throw new ArgumentNullException("key"); if(value == null) throw new ArgumentNullException("value"); IDocument target = FindKey(key); if(target == null) throw new IndexOutOfRangeException("The specified key was not found"); else dictionary[target] = value; } } /// /// Clears the dictionary. /// public void Clear() { mappings.Clear(); dictionary.Clear(); } /// /// Determines whether the dictionary contains an element. /// /// The key-value pair representing the element. /// true if the dictionary contains the element, false otherwise. public bool Contains(KeyValuePair item) { return ContainsKey(item.Key); } /// /// Gets a value indicating whether the dictionary is read-only. /// public bool IsReadOnly { get { return false; } } /// /// Copies the content of the dictionary to a key-value pairs array. /// /// The output array. /// The index at which the copy begins. /// If is null. public void CopyTo(KeyValuePair[] array, int arrayIndex) { if(array == null) throw new ArgumentNullException("array"); int i = 0; foreach(KeyValuePair pair in dictionary) { array[arrayIndex + i] = pair; i++; } } /// /// Returns an enumerator that iterates through the elements in the dictionary. /// /// The iterator. public IEnumerator> GetEnumerator() { return dictionary.GetEnumerator(); } /// /// Returns an enumerator that iterates through the elements in the dictionary. /// /// The iterator. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return dictionary.GetEnumerator(); } } }