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