/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System; using System.Collections; using System.Collections.Generic; using JetBrains.Omea.OpenAPI; namespace JetBrains.Omea.OpenApiEx { /// /// Represents a list of resource objects, accessibly by index and Resource ID. /// /// The resource object type. public class ResourceObjectsList : IResourceObjectsList where T : class, IResourceObject { /// /// The backing resource list. /// protected readonly IResourceList _resources; /// /// A factory wrapping the resources into resource objects. /// protected readonly IResourceObjectFactory _factory; /// /// A handler for adding existing objects to the list. /// protected readonly EventHandler _handlerAdd; /// /// A handler for removing objects from the list. /// protected readonly EventHandler _handlerRemove; /// /// Creates a read-only list from a resource list and a factory that wraps the raw resources into resource objects. /// /// The list of available resources, live or dead. /// The factory for wrapping the raw Omea resources into resource objects. public ResourceObjectsList(IResourceList resources, IResourceObjectFactory factory) : this(resources, factory, null, null) { } /// /// Creates a modifyable list from a resource list and a factory that wraps the raw resources into resource objects. /// The set of modification operations supported on the list is defined by the delegates you provide for adding and removing the items. /// /// The list of available resources, live or dead. /// The factory for wrapping the raw Omea resources into resource objects. /// A handler for adding new resources to the list. May be Null. /// A handler for adding new resources to the list. May be Null. public ResourceObjectsList(IResourceList resources, IResourceObjectFactory factory, EventHandler handlerAdd, EventHandler handlerRemove) { if(resources == null) throw new ArgumentNullException("resources"); if(factory == null) throw new ArgumentNullException("factory"); // Handlers may be Null _resources = resources; _factory = factory; _handlerAdd = handlerAdd; _handlerRemove = handlerRemove; } /// /// Gets the resource list wrapped by this list. /// public virtual IResourceList Resources { get { return _resources; } } /// /// Gets a resource object by the database ID of an Omea resource. /// Throws if no such resource in the list. /// /// The Omea resource database ID. /// The resource object. public T GetById(int id) { IResource resource = Core.ResourceStore.LoadResource(id); // Will throw if no such resource if(!_resources.Contains(resource)) throw new ArgumentOutOfRangeException("id", id, "A resource with the given identifier is not present in the list."); return _factory.CreateResourceObject(resource); } /// /// Gets a resource object by the database ID of an Omea resource. /// Returns Null if no such resource in the list. /// /// The Omea resource database ID. /// The resource object, or Null if not found. public T TryGetById(int id) { IResource resource = Core.ResourceStore.TryLoadResource(id); if(resource == null) return null; if(!_resources.Contains(resource)) return null; return _factory.CreateResourceObject(resource); } /// ///Determines the index of a specific item in the . /// /// /// ///The index of item if found in the list; otherwise, -1. /// /// ///The object to locate in the . public virtual int IndexOf(T item) { return _resources.IndexOf(item.Resource); } /// ///Inserts an item to the at the specified index. /// /// ///The object to insert into the . ///The zero-based index at which item should be inserted. ///The is read-only. ///index is not a valid index in the . public virtual void Insert(int index, T item) { if(_handlerAdd == null) throw new NotSupportedException(IsReadOnly ? "The list is read-only." : "This operation is not supported by the list."); _handlerAdd(this, new ResourceObjectEventArgs(item)); } /// ///Removes the item at the specified index. /// /// ///The zero-based index of the item to remove. ///The is read-only. ///index is not a valid index in the . public virtual void RemoveAt(int index) { if(_handlerRemove == null) throw new NotSupportedException(IsReadOnly ? "The list is read-only." : "This operation is not supported by the list."); _handlerRemove(this, new ResourceObjectEventArgs(this[index])); } /// ///Gets or sets the element at the specified index. /// /// /// ///The element at the specified index. /// /// ///The zero-based index of the element to get or set. ///index is not a valid index in the . ///The property is set and the is read-only. public virtual T this[int index] { get { return _factory.CreateResourceObject(_resources[index]); } set { throw new NotSupportedException("The items within this list do not have a persistent index."); } } /// ///Adds an item to the . /// /// ///The object to add to the . ///The is read-only. public virtual void Add(T item) { if(_handlerAdd == null) throw new NotSupportedException(IsReadOnly ? "The list is read-only." : "This operation is not supported by the list."); _handlerAdd(this, new ResourceObjectEventArgs(item)); } /// ///Removes all items from the . /// /// ///The is read-only. public virtual void Clear() { if(_handlerRemove == null) throw new NotSupportedException(IsReadOnly ? "The list is read-only." : "This operation is not supported by the list."); // Static snapshot T[] items; lock(_resources) // To keep Count and itemset in sync on live lists { items = new T[Count]; CopyTo(items, 0); } // Remove each foreach(T item in items) _handlerRemove(this, new ResourceObjectEventArgs(item)); } /// ///Determines whether the contains a specific value. /// /// /// ///true if item is found in the ; otherwise, false. /// /// ///The object to locate in the . public virtual bool Contains(T item) { return _resources.Contains(item.Resource); } /// ///Copies the elements of the to an , starting at a particular index. /// /// ///The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing. ///The zero-based index in array at which copying begins. ///arrayIndex is less than 0. ///array is null. ///array is multidimensional.-or-arrayIndex is equal to or greater than the length of array.-or-The number of elements in the source is greater than the available space from arrayIndex to the end of the destination array.-or-Type T cannot be cast automatically to the type of the destination array. public virtual void CopyTo(T[] array, int arrayIndex) { if(array == null) throw new ArgumentNullException("array"); if(arrayIndex < 0) throw new ArgumentOutOfRangeException("arrayIndex"); foreach(IResource resource in _resources) { if(arrayIndex >= array.Length) throw new ArgumentException("arrayIndex"); array[arrayIndex] = _factory.CreateResourceObject(resource); } } /// ///Removes the first occurrence of a specific object from the . /// /// /// ///true if item was successfully removed from the ; otherwise, false. This method also returns false if item is not found in the original . /// /// ///The object to remove from the . ///The is read-only. public virtual bool Remove(T item) { if(_handlerRemove == null) throw new NotSupportedException(IsReadOnly ? "The list is read-only." : "This operation is not supported by the list."); if(!Contains(item)) return false; _handlerRemove(this, new ResourceObjectEventArgs(item)); return true; } /// ///Gets the number of elements contained in the . /// /// /// ///The number of elements contained in the . /// /// public virtual int Count { get { return _resources.Count; } } /// ///Gets a value indicating whether the is read-only. /// /// /// ///true if the is read-only; otherwise, false. /// /// public virtual bool IsReadOnly { get { return (_handlerAdd != null) && (_handlerRemove != null); } } /// ///Returns an enumerator that iterates through the collection. /// /// /// ///A that can be used to iterate through the collection. /// ///1 IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_resources.GetEnumerator(), _factory); } /// ///Returns an enumerator that iterates through a collection. /// /// /// ///An object that can be used to iterate through the collection. /// ///2 public virtual IEnumerator GetEnumerator() { return new Enumerator(_resources.GetEnumerator(), _factory); } /// /// Implements the enumeration. /// public class Enumerator : IEnumerator, IEnumerator { private readonly IEnumerator _enumResources; private readonly IResourceObjectFactory _factory; protected T _current = null; public Enumerator(IEnumerator enumResources, IResourceObjectFactory factory) { _enumResources = enumResources; _factory = factory; } /// ///Advances the enumerator to the next element of the collection. /// /// /// ///true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection. /// /// ///The collection was modified after the enumerator was created. 2 public virtual bool MoveNext() { if(!_enumResources.MoveNext()) return false; _current = _factory.CreateResourceObject((IResource)_enumResources.Current); return true; } /// ///Sets the enumerator to its initial position, which is before the first element in the collection. /// /// ///The collection was modified after the enumerator was created. 2 public virtual void Reset() { _current = null; _enumResources.Reset(); } /// ///Gets the current element in the collection. /// /// /// ///The current element in the collection. /// /// ///The enumerator is positioned before the first element of the collection or after the last element. 2 object IEnumerator.Current { get { if(_current == null) throw new InvalidOperationException(); return _current; } } /// ///Gets the element in the collection at the current position of the enumerator. /// /// /// ///The element in the collection at the current position of the enumerator. /// /// public virtual T Current { get { if(_current == null) throw new InvalidOperationException(); return _current; } } /// ///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// ///2 public virtual void Dispose() { } } } }