using System;
using System.Data;
using System.Collections;
namespace Bttlxe.Data
{
/// <summary>
/// A strongly typed collection of key-and-value pairs for <see cref="DataItem"/> fields.
/// </summary>
/// <remarks>
/// <p>The <b>foreach</b> statement of the C# language (<b>for each</b> in Visual Basic) requires the type of
/// each element in the collection. Since each element of the <see cref="DataItemDictionary"/> is a key-and-value
/// pair, the element type is not the type of the key or the type of the value. Instead, the element type is
/// <see cref="DictionaryEntry"/>. For example:</p>
/// <code>foreach (DictionaryEntry myDE in myDataItemDictionary) {...}</code>
/// <p> The <b>foreach</b> statement is a wrapper around the enumerator, which only allows reading from, not
/// writing to, the collection.</p>
/// <p><see cref="DataItemDictionary"/> collections can be serialised.</p>
/// <seealso cref="DataItem"/>
/// </remarks>
[Serializable()]
public class DataItemDictionary : DictionaryBase
{
#region DictionaryBase Members
#region Properties
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <param name="key">The key whose value to get or set.</param>
/// <value>
/// The value associated with the specified key. If the specified key is not found, attempting to get
/// it returns a null reference (<see cref="Nothing"/> in Visual Basic), and attempting to set it creates
/// a new element using the specified key.
/// </value>
/// <remarks>
/// <p>This property provides the ability to access a specific element in the collection by using the
/// following syntax: <c>myCollection[key]</c>.</p>
/// <p>When setting this property, if the specified key already exists in the <see cref="DataItemDictionary"/>,
/// the value is replaced; otherwise, a new element is created. In contrast, the <see cref="Add"/> method does
/// not modify existing elements.</p>
/// </remarks>
public string this[string key]
{
get
{
return (string)Dictionary[key];
}
set
{
Dictionary[key] = value;
}
}
/// <summary>
/// Gets an <see cref="ICollection"/> containing the keys in the <see cref="DataItemDictionary"/>.
/// </summary>
/// <value>
/// An <see cref="ICollection"/> containing the keys in the <see cref="DataItemDictionary"/>.
/// </value>
/// <remarks>
/// <p>The order of the keys in the <see cref="ICollection"/> is unspecified, but it is the same order
/// as the associated values in the <see cref="ICollection"/> returned by the <see cref="Values"/> property.</p>
/// <p>The returned <see cref="ICollection"/> is not a static copy; instead, the <see cref="ICollection"/>
/// refers back to the keys in the original <see cref="DictionaryBase"/>. Therefore, changes to the
/// <see cref="DictionaryBase"/> continue to be reflected in the returned ICollection.</p>
/// </remarks>
public ICollection Keys
{
get
{
return Dictionary.Keys;
}
}
/// <summary>
/// Gets an <see cref="ICollection"/> containing the values in the <see cref="DataItemDictionary"/>.
/// </summary>
/// <value>
/// An <see cref="ICollection"/> containing the values in the <see cref="DataItemDictionary"/>.
/// </value>
/// <remarks>
/// <p>The order of the values in the <see cref="ICollection"/> is unspecified, but it is the same
/// order as the associated keys in the <see cref="ICollection"/> returned by the <see cref="Keys"/>
/// method.</p>
/// <p>The returned <see cref="ICollection"/> is not a static copy; instead, the <see cref="ICollection"/>
/// refers back to the values in the original <see cref="DictionaryBase"/>. Therefore, changes to the
/// <see cref="DictionaryBase"/> continue to be reflected in the returned <see cref="ICollection"/>.</p>
/// </remarks>
public ICollection Values
{
get
{
return Dictionary.Values;
}
}
#endregion
/// <summary>
/// Adds an element with the specified key and value into the <see cref="DataItemDictionary"/>.
/// </summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="value">The value of the element to add.</param>
/// <remarks>
/// <p>An object that has no correlation between its state and its hash code value should typically not
/// be used as the key. For example, <see cref="String"/> objects are better than <see cref="StringBuilder"/>
/// objects for use as keys.</p>
/// <p>The <see cref="Item"/> property can also be used to add new elements by setting the value of a key
/// that does not exist in the <see cref="DataItemDictionary"/>. For example:
/// <c>myCollection["myNonexistentKey"] = myValue</c>. However, if the specified key already exists in the
/// <see cref="DataItemDictionary"/>, setting the <see cref="Item"/> property overwrites the old value. In
/// contrast, the <see cref="Add"/> method does not modify existing elements.</p>
/// </remarks>
public void Add(string key, String value)
{
Dictionary.Add(key, value);
}
/// <summary>
/// Determines whether the <see cref="DataItemDictionary"/> contains a specific key.
/// </summary>
/// <param name="key">The key to locate in the <see cref="DataItemDictionary"/>.</param>
/// <returns><b>true</b> if the <see cref="DataItemDictionary"/> contains an element with the specified key;
/// otherwise, <b>false</b>.</returns>
public bool Contains(string key)
{
return Dictionary.Contains(key);
}
/// <summary>
/// Removes the element with the specified key from the <see cref="DataItemDictionary"/>.
/// </summary>
/// <param name="key">The key of the element to remove.</param>
/// <remarks>
/// If the <see cref="DataItemDictionary"/> does not contain an element with the specified key, the
/// <see cref="DataItemDictionary"/> remains unchanged. No exception is thrown.
/// </remarks>
public void Remove(string key)
{
Dictionary.Remove(key);
}
/// <summary>
/// Performs additional custom processes before inserting a new element into the underlying
/// <see cref="DictionaryBase"/> instance.
/// </summary>
/// <param name="key">The key of the element to insert.</param>
/// <param name="value">The value of the element to insert.</param>
protected override void OnInsert(Object key, Object value)
{
if (key.GetType() != Type.GetType("System.String"))
throw new ArgumentException("key must be of type System.String.", "key");
if (value.GetType() != Type.GetType("System.String"))
throw new ArgumentException( "value must be of type String.", "value" );
}
/// <summary>
/// Performs additional custom processes before removing an element from the underlying
/// <see cref="DictionaryBase"/> instance.
/// </summary>
/// <param name="key">The key of the element to remove.</param>
/// <param name="value">The value of the element to remove.</param>
protected override void OnRemove(Object key, Object value)
{
if (key.GetType() != Type.GetType("System.String"))
throw new ArgumentException("key must be of type System.String.", "key");
}
/// <summary>
/// Performs additional custom processes before setting a value in the underlying
/// <see cref="DictionaryBase"/> instance.
/// </summary>
/// <param name="key">The key of the element to locate.</param>
/// <param name="oldValue">The old value of the element associated with key.</param>
/// <param name="newValue">The new value of the element associated with key.</param>
protected override void OnSet(Object key, Object oldValue, Object newValue)
{
if (key.GetType() != Type.GetType("System.String") )
throw new ArgumentException("key must be of type System.String.", "key");
if (newValue.GetType() != Type.GetType("System.String"))
throw new ArgumentException("newValue must be of type System.String.", "newValue");
}
/// <summary>
/// Performs additional custom processes when validating the element with the specified key and value.
/// </summary>
/// <param name="key">The key of the element to validate.</param>
/// <param name="value">The value of the element to validate.</param>
protected override void OnValidate(Object key, Object value)
{
if (key.GetType() != Type.GetType("System.String"))
throw new ArgumentException("key must be of type System.String.", "key");
if (value.GetType() != Type.GetType("System.String"))
throw new ArgumentException("value must be of type System.String.", "value");
}
#endregion
}
/// <summary>
/// <p>A wrapper around a <see cref="DataSet"/> for transporting data between a data loader and a
/// data user.</p>
/// </summary>
/// <remarks>
/// <p>Data items are objects that can represent themselves as a <see cref="DataSet"/> with optional sorting
/// or conditional statements. A data item should not be treated as a data source as it is designed solely
/// for the transportation of data between loaders and a data user (which may or may not be the object implementing
/// the interface).</p>
/// <p>Framework objects implementing <see cref="IDataItem"/> are shown in the table below:</p>
/// <list type="table">
/// <listheader>
/// <term>Object</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term><see cref="DataItem"/></term>
/// <description>A generic implementation of a data item for handling custom objects.</description>
/// </item>
/// <item>
/// <term><see cref="News"/></term>
/// <description>A news item represents some common fields used with news releases.</description>
/// </item>
/// <item>
/// <term><see cref="NewsList"/></term>
/// <description>A list of <see cref="News"/> objects.</description>
/// </item>
/// </list>
/// <p>Objects implementing <see cref="IDataItem"/> objects which are serialisable should either implement the
/// <see cref="Data"/> property with the <see cref="NonSerializedAttribute"/> or else hide its own data properties
/// to prevent possible dupication.</p>
/// <seealso cref="DataItemDictionary"/>
/// <seealso cref="IDataLoader"/>
/// </remarks>
/// <example>
/// <p>For an example of a data item refer to the following example which demonstrates the correct usage of a data
/// loader and data item. (Note that the example uses the interfaces themselves to show the concept, you must
/// substitute them for objects implementing them in your own code.)</p>
/// <p class="lang">[C#]</p>
/// <code>
/// IDataLoader oLoader = new IDataLoader();
/// IDataItem oItem = new IDataItem();
/// oLoader.Execute(ref oItem, DataOperation.Read);
/// </code>
/// </example>
public interface IDataItem
{
/// <summary>
/// The data set.
/// </summary>
DataSet Data
{
get;
set;
}
/// <summary>
/// A data set containing the schema for this object.
/// </summary>
DataSet Schema
{
get;
}
/// <summary>
/// The condition clause.
/// </summary>
/// <value>
/// A T-SQL condition clause.
/// </value>
string Condition
{
get;
set;
}
/// <summary>
/// The sort string.
/// </summary>
/// <value>
/// A T-SQL ORDER BY string.
/// </value>
string Sort
{
get;
set;
}
}
}