/*
NOTICE OF CHANGES:
date of change: 3/11/2009
change: Externalized strings.
date of chagne: 3/17/2009
change: Strings in shared component must be externalized to a new project SMSharedStrings
*/
using System;
using System.Collections;
using TaskSchedulerInterop;
using SMStrings;
namespace TaskScheduler {
///
/// TriggerList is a collection of Triggers. Every Task has a TriggerList that is
/// created and destroyed automatically along with the Task. There are no public constructors.
///
///
///
/// A TriggerList can be empty, and indeed a newly created Task has an empty list.
/// It's not clear how the system handles a task with no triggers, however.
///
/// TriggerList implements IList and behaves like other indexable collections with one limitation:
/// You can't insert a Trigger at a position. Insert() throws NotImplementedException. This
/// restriction is based on the underlying API.
///
public class TriggerList : IList, IDisposable {
// Internal COM interface to access task that this list is associated with.
private ITask iTask;
// Trigger objects store in an ArrayList
private ArrayList oTriggers;
///
/// Internal constructor creates TriggerList using an ITask interface to initialize.
///
/// Instance of an ITask.
internal TriggerList(ITask iTask) {
this.iTask = iTask;
ushort cnt = 0;
iTask.GetTriggerCount(out cnt);
oTriggers = new ArrayList(cnt+5); //Allow for five additional entries without growing base array
for (int i=0; i
/// Enumerator for TriggerList; implements IEnumerator interface.
///
private class Enumerator : IEnumerator {
private TriggerList outer;
private int currentIndex;
///
/// Internal constructor - Only accessible through .
///
/// Instance of a TriggerList.
internal Enumerator(TriggerList outer) {
this.outer = outer;
Reset();
}
///
/// Moves to the next trigger. See for more information.
///
/// False if there is no next trigger.
public bool MoveNext() {
return ++currentIndex < outer.oTriggers.Count;
}
///
/// Reset trigger enumeration. See for more information.
///
public void Reset() {
currentIndex = -1;
}
///
/// Retrieves the current trigger. See for more information.
///
public object Current {
get { return outer.oTriggers[currentIndex]; }
}
}
#region Implementation of IList
///
/// Removes the trigger at a specified index.
///
/// Index of trigger to remove.
/// Index out of range.
public void RemoveAt(int index) {
if (index >= Count)
throw new ArgumentOutOfRangeException("index", index, SMSharedStringTable.GetString("SMSCHEDULER_FAILEDTOREMOVE_10"));
((Trigger)oTriggers[index]).Unbind(); //releases resources in the trigger
oTriggers.RemoveAt(index); //Remove the Trigger object from the array representing the list
iTask.DeleteTrigger((ushort)index); //Remove the trigger from the Task Scheduler
}
///
/// Not implemented; throws NotImplementedException.
/// If implemented, would insert a trigger at a specified index.
///
/// Index to insert trigger.
/// Value of trigger to insert.
void IList.Insert(int index, object value) {
throw new NotImplementedException(SMSharedStringTable.GetString("SMSCHEDULER_TRIGGERLISTDOE_21"));
}
///
/// Removes the trigger from the collection. If the trigger is not in
/// the collection, nothing happens. (No exception.)
///
/// Trigger to remove.
public void Remove(Trigger trigger) {
int i = IndexOf(trigger);
if (i != -1)
RemoveAt(i);
}
///
/// IList.Remove implementation.
///
void IList.Remove(object value) {
Remove(value as Trigger);
}
///
/// Test to see if trigger is part of the collection.
///
/// Trigger to find.
/// true if trigger found in collection.
public bool Contains(Trigger trigger) {
return (IndexOf(trigger) != -1);
}
///
/// IList.Contains implementation.
///
bool IList.Contains(object value) {
return Contains(value as Trigger);
}
///
/// Remove all triggers from collection.
///
public void Clear() {
for (int i = Count-1; i >= 0; i--) {
RemoveAt(i);
}
}
///
/// Returns the index of the supplied Trigger.
///
/// Trigger to find.
/// Zero based index in collection, -1 if not a member.
public int IndexOf(Trigger trigger) {
for (int i = 0; i < Count; i++) {
if (this[i].Equals(trigger))
return i;
}
return -1;
}
///
/// IList.IndexOf implementation.
///
int IList.IndexOf(object value) {
return IndexOf(value as Trigger);
}
///
/// Add the supplied Trigger to the collection. The Trigger to be added must be unbound,
/// i.e. it must not be a current member of a TriggerList--this or any other.
///
/// Trigger to add.
/// Index of added trigger.
/// Trigger being added is already bound.
public int Add(Trigger trigger) {
// if trigger is already bound a list throw an exception
if (trigger.Bound)
throw new ArgumentException(SMSharedStringTable.GetString("SMSCHEDULER_ATRIGGERCANNOT_5"));
// Add a trigger to the task for this TaskList
ITaskTrigger iTrigger;
ushort index;
iTask.CreateTrigger(out index, out iTrigger);
// Add the Trigger to the TaskList
trigger.Bind(iTrigger);
int index2 = oTriggers.Add(trigger);
// Verify index is the same in task and in list
if (index2 != (int)index)
throw new ApplicationException(SMSharedStringTable.GetString("SMSCHEDULER_ASSERTIONFAILU_4"));
return (int)index;
}
///
/// IList.Add implementation.
///
int IList.Add(object value) {
return Add(value as Trigger);
}
///
/// Gets read-only state of collection. Always false for TriggerLists.
///
public bool IsReadOnly {
get { return false; }
}
///
/// Access the Trigger at a specified index. Assigning to a TriggerList element requires
/// the value to unbound. The previous list element becomes unbound and lost,
/// while the newly assigned Trigger becomes bound in its place.
///
/// Collection index out of range.
public Trigger this[int index] {
get {
if (index >= Count)
throw new ArgumentOutOfRangeException("index", index, SMSharedStringTable.GetString("SMSCHEDULER_TRIGGERLISTCOL_23"));
return (Trigger)oTriggers[index];
}
set {
if (index >= Count)
throw new ArgumentOutOfRangeException("index", index, SMSharedStringTable.GetString("SMSCHEDULER_TRIGGERLISTCOL_23"));
Trigger previous = (Trigger)oTriggers[index];
value.Bind(previous);
oTriggers[index] = value;
}
}
///
/// IList.this[int] implementation.
///
object IList.this[int index] {
get { return this[index]; }
set { this[index] = (value as Trigger); }
}
///
/// Returns whether collection is a fixed size. Always returns false for TriggerLists.
///
public bool IsFixedSize {
get { return false; }
}
#endregion
#region Implementation of ICollection
///
/// Gets the number of Triggers in the collection.
///
public int Count {
get {
return oTriggers.Count;
}
}
///
/// Copies all the Triggers in the collection to an array, beginning at the given index.
/// The Triggers assigned to the array are cloned from the originals, implying they are
/// unbound copies. (Can't tell if cloning is the intended semantics for this ICollection method,
/// but it seems a good choice for TriggerLists.)
///
/// Array to copy triggers into.
/// Index at which to start copying.
public void CopyTo(System.Array array, int index) {
if (oTriggers.Count > array.Length - index) {
throw new ArgumentException(SMSharedStringTable.GetString("SMSCHEDULER_ARRAYHASINSUFF_3"));
}
for (int i = 0; i
/// Returns synchronizable state. Always false since the Task Scheduler is not
/// thread safe.
///
public bool IsSynchronized {
get { return false; }
}
///
/// Gets the root object for synchronization. Always null since TriggerLists aren't synchronized.
///
public object SyncRoot {
get { return null; }
}
#endregion
#region Implementation of IEnumerable
///
/// Gets a TriggerList enumerator.
///
/// Enumerator for TriggerList.
public System.Collections.IEnumerator GetEnumerator() {
return new Enumerator(this);
}
#endregion
#region Implementation of IDisposable
///
/// Unbinds and Disposes all the Triggers in the collection, releasing the com interfaces they hold.
/// Destroys the internal private pointer to the ITask com interface, but does not
/// specifically release the interface because it is also in the containing task.
///
public void Dispose() {
foreach (object o in oTriggers) {
((Trigger)o).Unbind();
}
oTriggers = null;
iTask = null;
}
#endregion
}
}