using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Diagnostics;
using System.Runtime;
using System.Runtime.Serialization;
using Tdo;
using Tdo.Common;
using Tdo.Common.Entities;
using Tdo.Common.Entities.Tables;
using Tdo.Common.Entities.Views;
using Tdo.Common.Helper;
using Tdo.Common.TdoSqlExpressionDom;
using Tdo.Common.TdoTypes;
namespace Tdo.Common.TdoTypes{
/// <summary>
/// Base class for all Tdo Types
/// </summary>
[CLSCompliant(true)]
[Serializable()]
[Browsable(false)]
[DesignTimeVisible(false)]
public abstract class TdoTypeBase<T> : IComponent, ITdoType<T>, INullable
where T : INullable, IXmlSerializable, new()//, IComparable
{
#region Fields
[NonSerialized()]
private ISite iSite;
/// <summary>
/// Flag
/// </summary>
protected bool beginEditInvoked;
/// <summary>
/// Field actualValue
/// </summary>
protected T actualValue;
/// <summary>
/// Old Value for restoring operations
/// </summary>
protected T oldValue;
/// <summary>
/// Reference to TDOTable class to which the field belongs to
/// </summary>
protected ITdoEntity pTdoEntity;
/// <summary>
/// Boolean that indicates if the field has been pModified by the last operation on DB
/// </summary>
protected internal bool pModified;
/// <summary>
/// Boolean that indicates wether the field can be NULL
/// </summary>
protected bool pAllowDBNull;
/// <summary>
/// Boolean that indicates if the field is IDENTITY
/// </summary>
protected bool pAutoIncrement;
/// <summary>
/// Long that indicates the start actualValue of the IDENTITY field
/// </summary>
protected long pAutoIncrementSeed;
/// <summary>
/// Long that indicates the actualValue increase of the IDENTITY field
/// </summary>
protected long pAutoIncrementStep;
/// <summary>
/// String that contains the name of the field except for ALIAS
/// </summary>
protected string pCaption;
/// <summary>
/// String that contains the name of the field
/// </summary>
protected string pColumnName;
/// <summary>
/// This contains the name of the field without "strange" characters
/// </summary>
protected internal string pColumnNameForParameter;
/// <summary>
/// Integer that indicates the length of the field. -1 indicates variable length or not determined
/// </summary>
protected int pMaxLength;
/// <summary>
///Boolean that indicates if the field is only reading
/// </summary>
protected bool pReadOnly = false;
/// <summary>
/// Boolean that indicates if a unique constraint exists
/// </summary>
protected bool pUnique;
/// <summary>
/// True if column is a constant expression, false otherwise.
/// </summary>
protected bool pIsConstant;
#endregion Fields
#region Constructors
/// <summary>
/// Default constructor
/// </summary>
protected TdoTypeBase()
{
this.pAllowDBNull = true;
this.pAutoIncrement = false;
this.pAutoIncrementSeed = 0;
this.pAutoIncrementStep = 0;
this.pColumnName = String.Empty;
this.pCaption = String.Empty;
this.pColumnNameForParameter = String.Empty;
this.pMaxLength = -1;
this.TdoEntity = new TdoEntityBase();
this.pModified = false;
this.pReadOnly = false;
this.pUnique = false;
this.pIsConstant = false;
this.beginEditInvoked = false;
}
/// <summary>
/// Constructor of TDOTypeBase class
/// </summary>
/// <param name="allowDBNull">Boolean that indicates wether the field can be NULL</param>
/// <param name="autoIncrement">Boolean that indicates if the field is IDENTITY (auto-increase)</param>
/// <param name="autoIncrementSeed">Long that indicates how much is increasing the IDENTITY field</param>
/// <param name="autoIncrementStep">Long that indicates the start actualValue of the IDENTITY field </param>
/// <param name="caption">String that indicates the heading/columnAlias of the field</param>
/// <param name="columnName">String that indicates the name of the column (field)</param>
/// <param name="maxLength">Integer that indicates the maximum length of the field (-1,field without limit)</param>
/// <param name="readOnly">Boolean that indicates if the field is only reading</param>
/// <param name="unique">Boolean that indicates if a unique constraint exists on that field</param>
/// <param name="tdoEntity">TdoEntity referenced to the class that contains the field</param>
protected TdoTypeBase(bool allowDBNull, bool autoIncrement, long autoIncrementSeed,
long autoIncrementStep, string caption, string columnName, int maxLength,
bool readOnly, bool unique, ITdoEntity tdoEntity)
: this()
{
this.pAllowDBNull = allowDBNull;
this.pAutoIncrement = autoIncrement;
this.pAutoIncrementSeed = autoIncrementSeed;
this.pAutoIncrementStep = autoIncrementStep;
this.pCaption = caption;
this.ColumnName = columnName;
this.pMaxLength = maxLength;
this.pReadOnly = readOnly;
this.pUnique = unique;
this.pModified = false;
this.pTdoEntity = tdoEntity;
this.pIsConstant = false;
}
#endregion Constructors
#region Properties
/// <summary>
/// Boolean that indicates wether the field can be NULL
/// </summary>
[XmlAttribute()]
[Browsable(false)]
public bool AllowDBNull
{
get
{
return this.pAllowDBNull;
}
set
{
this.pAllowDBNull = value;
}
}
/// <summary>
/// Boolean that indicates if the field is IDENTITY
/// </summary>
[XmlAttribute()]
[Browsable(false)]
public bool AutoIncrement
{
get
{
return this.pAutoIncrement;
}
set
{
this.pAutoIncrement = value;
}
}
/// <summary>
/// Long that indicates the start actualValue of the IDENTITY field
/// </summary>
[XmlAttribute()]
[Browsable(false)]
public long AutoIncrementSeed
{
get
{
return this.pAutoIncrementSeed;
}
set
{
this.pAutoIncrementSeed = value;
}
}
/// <summary>
/// Long that indicates the actualValue increase of the IDENTITY field
/// </summary>
[XmlAttribute()]
[Browsable(false)]
public long AutoIncrementStep
{
get
{
return this.pAutoIncrementStep;
}
set
{
this.pAutoIncrementStep = value;
}
}
/// <summary>
/// String that contains the name of the field except for ALIAS
/// </summary>
[XmlAttribute()]
[Browsable(false)]
public string Caption
{
get
{
return this.pCaption;
}
set
{
this.pCaption = value;
}
}
/// <summary>
/// String that contains the name of the field
/// </summary>
[XmlAttribute()]
[Browsable(false)]
public string ColumnName
{
get
{
return this.pColumnName;
}
set
{
this.pColumnName = value;
this.pColumnNameForParameter = "@"+TdoTypeBase<T>.TransformToVariable(this.pColumnName.Replace("[","").Replace("]",""));
}
}
/// <summary>
/// String that contains the name of the field parameter
/// </summary>
[Browsable(false)]
string ITdoColumn.ColumnNameForParameter //explicit implementation
{
get
{
return this.pColumnNameForParameter;
}
set
{
this.pColumnNameForParameter = value;
}
}
/// <summary>
/// Gets the column name for DataTable objects.
/// </summary>
/// <value>The column name for DataTable.</value>
[XmlAttribute()]
[Browsable(false)]
public string ColumnNameForDataTable
{
get
{
return this.pColumnName.TrimStart('[').TrimEnd(']');
}
}
/// <summary>
/// Integer that indicates the length of the field. -1 indicates variable length or not determined
/// </summary>
[XmlAttribute()]
[Browsable(false)]
public int MaxLength
{
get
{
return this.pMaxLength;
}
set
{
this.pMaxLength = value;
}
}
/// <summary>
/// System.Data.SqlDbType of ITdoColumn
/// </summary>
[XmlAttribute()]
[Browsable(false)]
public virtual SqlDbType SqlDbType
{
get
{
return System.Data.SqlDbType.Variant;
}
}
/// <summary>
/// Boolean that indicates if a unique constraint exists
/// </summary>
[XmlAttribute()]
[Browsable(false)]
public bool Unique
{
get
{
return this.pUnique;
}
set
{
this.pUnique = value;
}
}
/// <summary>
/// Returns or sets the Table to which the TDO field belongs to and shares resources
/// </summary>
[XmlIgnore]
[Browsable(false)]
public ITdoEntity TdoEntity
{
get
{
return this.pTdoEntity;
}
set
{
this.pTdoEntity = value;
}
}
/// <summary>
/// Return or Set Field Value
/// </summary>
[Browsable(false)]
public T Value
{
get
{
return this.actualValue;
}
set
{
//if (this.ReadOnly)
// throw new InvalidOperationException("Field is read only");
if (!this.beginEditInvoked)
{
this.BeginEdit();
}
this.actualValue = value;
this.pModified = true;
}
}
/// <summary>
/// Get or Set Value property of Object type
/// </summary>
[XmlIgnore]
[Browsable(false)]
public abstract object ObjectValue { get; set;}
//public virtual object ObjectValue
//{
// get
// {
// return (object)this.actualValue;
// }
// set
// {
// this.Value = (TdoEntityType)value;
// }
//}
/// <summary>
/// Return True if Value has been pModified otherwise false
/// </summary>
[XmlAttribute()]
[Browsable(false)]
public bool Modified
{
get
{
return this.pModified;
}
}
/// <summary>
/// Gets or sets if column is a constant expression.
/// </summary>
/// <remarks>
/// True for Value, false for Column.
/// </remarks>
[XmlIgnore()]
[Browsable(false)]
public virtual bool IsConstant
{
get
{
return this.pIsConstant;
}
set
{
this.pIsConstant = value;
}
}
/// <summary>
///Boolean that indicates if the field is only reading
/// </summary>
[XmlAttribute()]
[Browsable(false)]
public bool ReadOnly
{
get
{
return this.pReadOnly;
}
set
{
this.pReadOnly = value;
}
}
#endregion Properties
#region Methods
/// <summary>
/// Returns the name of the field in a format useful like a parameter
/// </summary>
/// <param name="name">Name of the field</param>
/// <returns>Parameter name without "" or strange characters</returns>
protected static string TransformToVariable(string name)
{
string ris = String.Empty;
if (String.IsNullOrEmpty(name)) return ris;
char[] nc = name.ToCharArray();
//Substitute any characters not in a..z 0..9 with
//a = 97
//z = 122
//A = 65
//Z = 90
//0 = 48
//9 = 57
//_ = 95
for (int i = 0; i < nc.Length; i++)
{
if (!((nc[i] >= 'a' && nc[i] <= 'z')
|| (nc[i] >= 'A' && nc[i] <= 'Z')
|| (nc[i] >= '0' && nc[i] <= '9')
|| (nc[i] == '_')
))
{
ris += "_";
}
else
{
ris += nc[i].ToString();
}
}
if (ris.ToCharArray()[0] >= '0' && ris.ToCharArray()[0] <= '9')
{
ris = "_" + ris;
}
while (ris.Substring(ris.Length - 1, 1) == "_")
{
ris = ris.Substring(0, ris.Length - 1); //Remove the last increase _
}
return ris;
}
/// <summary>
/// Define an columnAlias, setting pCaption property
/// </summary>
/// <param name="columnAlias">Column columnAlias (columnname as [columnAlias])</param>
/// <returns></returns>
public ITdoType<T> Alias(string columnAlias)
{
this.pCaption = columnAlias;
return this;
}
/// <summary>
/// Saves the state of the fields and allows to modify the values. Call BeginEdit() before modifying the values of the fields
/// </summary>
public virtual void BeginEdit()
{
//if (this.ReadOnly)
// throw new InvalidOperationException("Field is read only");
this.beginEditInvoked = true;
this.pModified = false;
this.oldValue = this.ClonedValue(true);
}
/// <summary>
/// Ends modifying the values and keeps a copy of the values in case of a CancelEdit(). Call EndEdit() before invoking Inert,Update,Delete methods.
/// </summary>
public virtual void EndEdit()
{
this.beginEditInvoked = false;
}
/// <summary>
/// Ends modifying the values and restores the original ones.Call CancelEdit() to restore all the original values before having invoked the BeginEdit() method.
/// </summary>
public virtual void CancelEdit()
{
this.beginEditInvoked = false;
this.actualValue = this.ClonedValue(false);
this.pModified = false;
}
/// <summary>
/// Returns the name of the field with a suffix if this has been changed
/// Otherwise it returns ""
/// </summary>
/// <param name="suffix">Suffix to set after the name of the field</param>
/// <returns>Returns an expression like TDOSqlExpression useful to convert the where clause to string</returns>
internal string NameIfModified(string suffix)
{
return (this.pModified ? this.ColumnName + suffix : String.Empty);
}
/// <summary>
/// Returns the name of the field with a suffix if this has been changed
/// Otherwise it returns ""
/// </summary>
/// <param name="prefix">Prefix to set before the name of the field</param>
/// <param name="suffix">Suffix to set after the name of the field</param>
/// <returns>Returns an expression like TDOSqlExpression useful to convert the where clause to string</returns>
internal string NameIfModified(string prefix, string suffix)
{
return (this.pModified ? prefix + this.pColumnNameForParameter + suffix : String.Empty);
}
/// <summary>
/// Comparison operator Equal
/// </summary>
/// <param name="obj">Object to compare</param>
/// <returns>Returns an expression like TDOSqlExpression useful to convert the where clause to string</returns>
public override bool Equals(object obj)
{
return base.Equals(obj);
}
/// <summary>
/// Returns Hash code
/// </summary>
/// <returns>Returns an expression like TDOSqlExpression useful to convert the where clause to string</returns>
public override int GetHashCode()
{
return base.GetHashCode();
}
/// <summary>
/// Returns the qualified name of the object
/// </summary>
/// <returns>string</returns>
public new virtual string ToString()
{
return this.Value.ToString();
}
/// <summary>
/// Create a copy of the current TdoColumn
/// </summary>
/// <returns>TdoEntityType</returns>
public abstract ITdoType<T> Clone();
/// <summary>
/// Create a copy of toClone Value property
/// </summary>
/// <param name="actualValue">True to clone actualValue property, False to clone oldValue property</param>
/// <returns>TdoEntityType</returns>
internal abstract T ClonedValue(bool actualValue);
/// <summary>
/// Create a copy of Value property
/// </summary>
/// <returns></returns>
public T ClonedValue()
{
return this.ClonedValue(true);
}
#region INullable Members
/// <summary>
/// Indicates whether value is Null.
/// </summary>
[Browsable(false)]
public bool IsNull
{
get
{
return this.Value.IsNull;
}
}
#endregion
#endregion Methods
#region Static Methods
/// <summary>
/// Return column.ObjectValue.ToString() if IsConstant==true, column.TdoEntity.EntityName.columnName otherwise.
/// </summary>
/// <returns>Column or Value string</returns>
public static string ColumnOrValue(ITdoColumn column)
{
if (column.IsConstant)
return column.ObjectValue.ToString();
else
return (!String.IsNullOrEmpty(column.TdoEntity.EntityName) ? column.TdoEntity.EntityName + "." : String.Empty) + column.ColumnName + (!String.IsNullOrEmpty(column.Caption) ? " as [" + column.Caption + "] " : String.Empty);
}
#endregion Static Methods
//#region IXmlSerializable Members
///// <summary>
///// This property is reserved, apply the System.Xml.Serialization.XmlSchemaProviderAttribute to the class instead.
///// </summary>
///// <returns>An System.Xml.Schema.XmlSchema that describes the XML representation of the object that is produced by the System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter) method and consumed by the System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader) method.</returns>
//public System.Xml.Schema.XmlSchema GetSchema()
//{
// //XmlSchema schema = new XmlSchema();
// //// <xs:element name="cat" type="xs:string"/>
// //XmlSchemaAttribute attributeAllowDBNull = new XmlSchemaAttribute();
// //attributeAllowDBNull.Name = "allowDBNull";
// //attributeAllowDBNull.SchemaTypeName = new XmlQualifiedName("bool", "http://www.w3.org/2001/XMLSchema");
// //schema.Items.Add(attributeAllowDBNull);
// //return schema;
// return null;
//}
///// <summary>
///// Reads XML data into the TdoTypeBase using the specified System.Xml.XmlReader.
///// </summary>
///// <param name="reader">The System.Xml.XmlReader from which to read.</param>
//public virtual void ReadXml(XmlReader reader)
//{
// reader.ReadStartElement("TdoTypeBase");
// reader.ReadStartElement("allowDBNull"); this.pAllowDBNull = bool.Parse(reader.ReadString()); reader.ReadEndElement();
// reader.ReadStartElement("autoIncrement"); this.pAutoIncrement = bool.Parse(reader.ReadString()); reader.ReadEndElement();
// reader.ReadStartElement("autoIncrementSeed"); this.pAutoIncrementSeed = long.Parse(reader.ReadString()); reader.ReadEndElement();
// reader.ReadStartElement("autoIncrementStep"); this.pAutoIncrementStep = long.Parse(reader.ReadString()); reader.ReadEndElement();
// reader.ReadStartElement("caption"); this.pCaption = reader.ReadString(); reader.ReadEndElement();
// reader.ReadStartElement("columnName"); this.pColumnName = reader.ReadString(); reader.ReadEndElement();
// reader.ReadStartElement("IsConstant"); this.pIsConstant = bool.Parse(reader.ReadString()); reader.ReadEndElement();
// reader.ReadStartElement("Modified"); this.pModified = bool.Parse(reader.ReadString()); reader.ReadEndElement();
// reader.ReadStartElement("maxLength"); this.pMaxLength = int.Parse(reader.ReadString()); reader.ReadEndElement();
// reader.ReadStartElement("readOnly"); this.pReadOnly = bool.Parse(reader.ReadString()); reader.ReadEndElement();
// reader.ReadStartElement("unique"); this.pUnique = bool.Parse(reader.ReadString()); reader.ReadEndElement();
// reader.ReadEndElement();
//}
///// <summary>
///// Converts TdoTypeBase into its Xml representation.
///// </summary>
///// <param name="writer">The System.Xml.XmlWriter with which to write. </param>
//public virtual void WriteXml(XmlWriter writer)
//{
// writer.WriteStartElement("TdoTypeBase");
// writer.WriteStartElement("allowDBNull"); writer.WriteString(this.pAllowDBNull.ToString()); writer.WriteEndElement();
// writer.WriteStartElement("autoIncrement"); writer.WriteString(this.pAutoIncrement.ToString()); writer.WriteEndElement();
// writer.WriteStartElement("autoIncrementSeed"); writer.WriteString(this.pAutoIncrementSeed.ToString()); writer.WriteEndElement();
// writer.WriteStartElement("autoIncrementStep"); writer.WriteString(this.pAutoIncrementStep.ToString()); writer.WriteEndElement();
// writer.WriteStartElement("caption"); writer.WriteString(this.pCaption); writer.WriteEndElement();
// writer.WriteStartElement("columnName"); writer.WriteString(this.pColumnName); writer.WriteEndElement();
// writer.WriteStartElement("IsConstant"); writer.WriteString(this.pIsConstant.ToString()); writer.WriteEndElement();
// writer.WriteStartElement("Modified"); writer.WriteString(this.pModified.ToString()); writer.WriteEndElement();
// writer.WriteStartElement("maxLength"); writer.WriteString(this.pMaxLength.ToString()); writer.WriteEndElement();
// writer.WriteStartElement("readOnly"); writer.WriteString(this.pReadOnly.ToString()); writer.WriteEndElement();
// writer.WriteStartElement("unique"); writer.WriteString(this.pUnique.ToString()); writer.WriteEndElement();
// writer.WriteEndElement();
//}
//#endregion
#region IComponent Members
/// <summary>
/// Disposed event.
/// </summary>
public event EventHandler Disposed;
/// <summary>
/// Gets or sets the <see cref="T:System.ComponentModel.ISite"></see> associated with the <see cref="T:System.ComponentModel.IComponent"></see>.
/// </summary>
/// <value></value>
/// <returns>The <see cref="T:System.ComponentModel.ISite"></see> object associated with the component; or null, if the component does not have a site.</returns>
[XmlIgnore()]
public ISite Site
{
get
{
return this.iSite;
}
set
{
this.iSite = value;
}
}
#endregion
#region IDisposable Members
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
if (this.Disposed != null)
this.Disposed(this, EventArgs.Empty);
GC.SuppressFinalize(this);
}
#endregion
}
}
|