/*********************************************************************/
/* */
/* AgentService Framework */
/* www.agentservice.it */
/* */
/* Copyright (C) 2007 l.i.d.o. - DIST, University of Genoa, Italy */
/* GNU Lesser General Public License */
/* */
/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Lesser General Public */
/* License as published by the Free Software Foundation, */
/* version 2.1 of the License. */
/* */
/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
/* Lesser General Public License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public */
/* License along with this library; if not, write to the */
/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */
/* Boston, MA 02111-1307, USA. */
/* */
/*********************************************************************/
using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Collections;
namespace AgentService.Install.XmlDataModel
{
///
/// Class XmlPropertyInfo. Stores the information
/// about a key-value pair, that is persisted on
/// an xml stream as simple tag which has two
/// attributes: the name and the value of the
/// property.
///
[XmlRoot(ElementName="property")]
public class XmlPropertyInfo : ICloneable
{
///
/// name of the propery.
///
protected string name;
///
/// Gets the name of the propery
///
[XmlAttribute(AttributeName="name")]
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
///
/// value of the property
///
protected string value;
///
/// Gets, sets the value of
/// the property.
///
[XmlAttribute(AttributeName="value")]
public string Value
{
get
{
return this.value;
}
set
{
this.value = value;
}
}
///
/// Constructs an instance of the XmlPropertyInfo class.
///
public XmlPropertyInfo()
{
this.name = string.Empty;
this.value = string.Empty;
}
///
/// Constructs an instance of the XmlPropertyInfo class.
///
/// name of the property
/// value of the property
public XmlPropertyInfo(string name, string value)
{
this.name = name;
this.value = value;
}
#region ICloneable Members
///
/// Clones this instance of XmlPropertyInfoCollection.
///
/// identical copy of the object
public object Clone()
{
XmlPropertyInfo clone = new XmlPropertyInfo();
clone.name = this.name.Clone() as string;
clone.value = this.value.Clone() as string;
return clone;
}
#endregion
}
///
/// Class XmlPropertyInfoCollection. Specialized Collection of XmlPropertyInfo objects
///
[Serializable]
[XmlRoot(ElementName = "additional")]
public class XmlPropertyInfoCollection : ICollection, IEnumerator, IEnumerable, IXmlSerializable, ICloneable
{
///
/// InitialDimension, default value of the Size of the collection
///
private readonly static int InitialDimension = 10;
///
/// incFactor, defines the increment factor when the internal data structure
/// needs to increase in Size
///
private int incFactor = 2;
///
/// Size of the collection
///
private int size = 0;
///
/// index of the current element in the collection
///
private int index = 0;
///
/// internal data structure that stores the XmlPropertyInfoXmlPropertyInfo objects
///
private XmlPropertyInfo[] items;
///
/// Constructs an empty collection with initial Size equal to
/// XmlPropertyInfoCollection.InitialDimension
///
public XmlPropertyInfoCollection()
{
this.items = new XmlPropertyInfo[XmlPropertyInfoCollection.InitialDimension];
this.index = -1;
}
///
/// Constructs an empty collection with initial Size equal to
/// the argument, if the argument is less than 1 the collection
/// is constructed by using the default Size
///
/// initial dimension of the collection
public XmlPropertyInfoCollection(int initialDimension)
{
if (initialDimension > 0)
{
this.items = new XmlPropertyInfo[initialDimension];
}
else
{
this.items = new XmlPropertyInfo[XmlPropertyInfoCollection.InitialDimension];
}
this.index = -1;
}
///
/// Constructs an empty collection with initial Size equal to the first argument
/// and increment factor equal to second parameter. If the supplied initial Size is less than 1
/// the constructor will use the default Size, while if the increment factor is less than 1 it
/// will be ignored
///
/// initial Size of the collection
/// increment factor
public XmlPropertyInfoCollection(int initialDimension, int incFactor)
{
if (initialDimension > 0)
{
this.items = new XmlPropertyInfo[initialDimension];
}
else
{
this.items = new XmlPropertyInfo[XmlPropertyInfoCollection.InitialDimension];
}
if (incFactor > 0)
{
this.incFactor = incFactor;
}
this.index = -1;
}
#region ICollection Methods
///
/// Gets the number of the elements actually stored in the collection
///
public int Count
{
get
{
return size;
}
}
///
/// true if the collection is synchronized
///
public bool IsSynchronized
{
get
{
return false;
}
}
///
/// Gets the sinchronization object for the collection
///
public object SyncRoot
{
get
{
return null;
}
}
///
/// Copies the elements of the collection into a System.Array object, starting at the given index.
/// Throws NullArgumetException if the supplied array is null.
/// Throws ArgumentOutOfRangeException if
/// - the index argument is negative
/// - the index argument is greater than the array's Size
/// - the sum of the index argument and of the collection Size is greater then the array's Size
/// - the rank of the array argument is greater than 1
///
/// array where the items of the collection will be copied to
/// starting index
public void CopyTo(System.Array array, int index)
{
if (array == null) throw new ArgumentNullException("array", "the argument cannot be null");
if (index < 0) throw new ArgumentOutOfRangeException("index", index, "the index must be >= 0");
if (array.Length <= index) throw new ArgumentOutOfRangeException("index", index, "index is greater then array Size");
if (array.Length < index + this.size) throw new ArgumentOutOfRangeException("index", index, "the index value is too forward for the insertion of the elements in the collection");
if (array.Rank != 1) throw new ArgumentOutOfRangeException("array", array, "the array has more than one dimension");
for (int ndx = 0; ndx < this.size; ndx++)
array.SetValue(this.items[ndx], index + ndx);
}
#endregion
#region IEnumerable Methods
///
/// returns the enumerator object for the collection
///
/// enumerator for the collection
public IEnumerator GetEnumerator()
{
this.Reset();
return this;
}
#endregion
#region IEnumerator Methods
///
/// gets the current object for the collection
///
public object Current
{
get
{
if ((this.index < this.size) && (this.index > -1))
return this.items[index];
else
return null;
}
}
///
/// resets the collection enumerator
///
public void Reset()
{
this.index = -1;
}
///
/// moves to the next element of the collection.
///
/// false if there are no more elements to navigate, true otherwise
public bool MoveNext()
{
this.index++;
return (this.index < this.size);
}
#endregion
///
/// adds a property to the collection
///
/// property name
/// property value
public void Add(string name, string value)
{
this.Add(new XmlPropertyInfo(name, value));
}
///
/// adds a non null item to the collection
///
/// item to Add
public void Add(XmlPropertyInfo item)
{
if (item == null)
throw new ArgumentNullException("item", "cannot Add a null item");
if (this.size >= this.items.Length)
{
int ndx;
XmlPropertyInfo[] backing = new XmlPropertyInfo[this.size * this.incFactor];
for (ndx = 0; ndx < this.size; ndx++)
backing[ndx] = this.items[ndx];
backing[ndx] = item;
this.size = ndx + 1;
this.items = backing;
}
else
this.items[size++] = item;
}
///
/// Remove the first occurrence of the element equal to the argument
///
/// item to Remove
public void Remove(XmlPropertyInfo item)
{
if (item != null)
{
int found = size;
int finalSize = size;
for (int ndx = 0; ndx < this.size; ndx++)
{
if ((this.items[ndx] == item) && (found == this.size))
{
found = ndx;
finalSize--;
}
if (found < ndx)
{
this.items[found++] = this.items[ndx];
}
}
if (size > finalSize)
{
this.items[size - 1] = null;
}
this.size = finalSize;
}
}
///
/// Removes all the messages from each agent queue
///
public void Clear()
{
this.items = null;
this.items = new XmlPropertyInfo[XmlPropertyInfoCollection.InitialDimension];
this.size = 0;
}
///
/// true if the collection Contains the supplied item
///
/// item candidate
/// true if found false otherwise
public bool Contains(XmlPropertyInfo item)
{
return (this.IndexOf(item) != -1);
}
///
/// returns the index of the item passed as argument
///
/// item to found
/// zero-based index of the item, -1 otherwise
public int IndexOf(XmlPropertyInfo item)
{
int retval = -1;
for (int ndx = 0; ndx < this.size; ndx++)
if (this.items[ndx] == item)
retval = ndx;
return retval;
}
///
/// returns the item at the given position in the collection
///
/// position of the item
/// the item at the desired position
public XmlPropertyInfo this[int index]
{
get
{
if (index >= this.size)
throw new IndexOutOfRangeException(String.Format("index {0} is greater or equal than the collection Size [{1}]", index, this.size));
return this.items[index];
}
set
{
if (index >= this.size)
throw new IndexOutOfRangeException(String.Format("index {0} is greater or equal than the collection Size [{1}]", index, this.size));
if (value == null)
throw new NullReferenceException("Cannot insert a null item into the collection");
this.items[index] = value;
}
}
///
/// Adds all the entries contained in the given collection
///
/// collection of items to Add
public void AddAll(XmlPropertyInfoCollection entries)
{
int needed = entries.size;
int maxLen = this.size + needed;
if ((this.items.Length - this.size) < needed)
{
XmlPropertyInfo[] backing = new XmlPropertyInfo[maxLen];
for (int i = 0; i < this.size; i++)
{
backing[i] = this.items[i];
}
this.items = backing;
}
for (int offset = this.size; this.size < maxLen; this.size++)
{
this.items[this.size] = entries.items[this.size - offset];
}
}
#region IXmlSerializable Members
///
/// Writes to the Xml writer this
/// collection as an XML node.
///
/// xml writer
public void WriteXml(XmlWriter writer)
{
//MOD: 17/05/2006 Marco Garr : added code to Remove annoying xmlns:xssi from file
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer serializer = new XmlSerializer(typeof(XmlPropertyInfo));
for (int ndx = 0; ndx < this.size; ndx++)
{
serializer.Serialize(writer, this.items[ndx],ns);
}
writer.WriteEndElement();
}
///
/// Gets the XML schema of the collection
///
/// null
public System.Xml.Schema.XmlSchema GetSchema()
{
// TODO: Add Site.GetSchema implementation
return null;
}
///
/// Reads from the XML stream a collection object.
///
/// xml reader
public void ReadXml(XmlReader reader)
{
// Reads the element enclosing the object
reader.ReadStartElement();
if (reader.LocalName == "property")
{
reader.MoveToContent();
// Reads the "data" element
XmlSerializer serializer = new XmlSerializer(typeof(XmlPropertyInfo));
while (reader.NodeType != XmlNodeType.EndElement)
{
XmlPropertyInfo XmlPropertyInfo = (XmlPropertyInfo)serializer.Deserialize(reader);
this.Add(XmlPropertyInfo);
}
reader.ReadEndElement();
}
}
#endregion
#region ICloneable Members
///
/// Clones this instance of XmlPropertyInfoCollection.
///
/// identical copy of the object
public object Clone()
{
XmlPropertyInfoCollection clone = new XmlPropertyInfoCollection(this.items.Length, this.incFactor);
clone.index = index;
clone.size = size;
for (int ndx = 0; ndx < this.size; ndx++)
{
clone.items[ndx] = this.items[ndx].Clone() as XmlPropertyInfo;
}
return clone;
}
#endregion
}
}