Files
2018-06-29 19:47:36 +00:00

724 lines
18 KiB
C#

///////////////////////////////////////////////////////////
// IntegrationMap.cs
// Implementation of Class IntegrationMap
// CSLA type: Editable Child
// Created on: 09-Feb-2006
// Object design: John
// Coded: John 09-Feb-2006
///////////////////////////////////////////////////////////
using System;
using System.Data;
using CSLA.Data;
using GZTW.Data;
using CSLA;
using System.Threading;
using CSLA.Security;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace GZTW.AyaNova.BLL
{
/// <summary>
/// Map to tie an integration application's data
/// to AyaNova object records
///
/// For example:
/// In QuickBooks integration for the optional
/// QBI product this object maps
/// between QuickBooks objects and their
/// corresponding AyaNova object.
/// </summary>
[Serializable]
public class IntegrationMap : BusinessBase
{
#region Attributes
//Kept for compatibility reasons
//Users will have their own security for this stuff
private bool bReadOnly=false;
private Guid mID;
private Guid mCreator;
private Guid mModifier;
private SmartDate mCreated;
private SmartDate mModified;
/// <summary>
/// ID of parent integration object
/// </summary>
private Guid mIntegrationID;
/// <summary>
/// ID of AyaNova Object
/// </summary>
private Guid mRootObjectID=Guid.NewGuid();
private RootObjectTypes mRootObjectType;
private string mForeignID=null;
private string mName="";
private SmartDate mLastSync;
private object mMapObject=null;
private string mForeignCheckSum="";
private string mAyaNovaCheckSum="";
#endregion
#region Constructor
private IntegrationMap()
{
//Child object
MarkAsChild();
//New ID
mID = Guid.NewGuid();
//Set record history to defaults
mCreated = new SmartDate(DBUtil.CurrentWorkingDateTime);
mModified=new SmartDate();
mCreator=Guid.Empty;
mModifier=Guid.Empty;
RootObjectID=Guid.Empty;
this.RootObjectType=RootObjectTypes.Nothing;
ForeignID="";
mLastSync = new SmartDate(DBUtil.CurrentWorkingDateTime);
}
#endregion
#region Business Properties
//---Common properties
/// <summary>
/// Initial created date of this object
/// </summary>
public string Created
{
get
{
return mCreated.ToString();
}
}
/// <summary>
/// User ID of who initially created this object
/// </summary>
public Guid Creator
{
get
{
return mCreator;
}
}
/// <summary>
/// Last modified date of this object
/// </summary>
public string Modified
{
get
{
return mModified.ToString();
}
}
/// <summary>
/// User ID of who last modified this object
/// </summary>
public Guid Modifier
{
get
{
return mModifier;
}
}
/// <summary>
/// Unique ID of this object
/// </summary>
public Guid ID
{
get
{
return mID;
}
}
//---IntegrationMap specific properties
/// <summary>
/// ID of parent integration object
/// </summary>
public Guid IntegrationID
{
get
{
return mIntegrationID;
}
}
/// <summary>
/// AyaNova object ID
/// </summary>
public Guid RootObjectID
{
get
{
return mRootObjectID;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if(mRootObjectID!=value)
{
mRootObjectID = value;
BrokenRules.Assert("RootObjectID","Error.Object.RequiredFieldEmpty,IntegrationMap.Label.RootObjectID","RootObjectID",value==Guid.Empty);
MarkDirty();
}
}
}
}
/// <summary>
/// AyaNova object type
/// </summary>
public RootObjectTypes RootObjectType
{
get
{
return mRootObjectType;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if(mRootObjectType!=value)
{
mRootObjectType = value;
BrokenRules.Assert("RootObjectType","Error.Object.RequiredFieldEmpty,IntegrationMap.Label.RootObjectType","RootObjectType",value==RootObjectTypes.Nothing);
MarkDirty();
}
}
}
}
/// <summary>
/// Set/get Foreign ID
/// This is the integration object ID
/// Required, 255 ASCII characters max
/// </summary>
public string ForeignID
{
get
{
return mForeignID;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if(mForeignID!=value)
{
mForeignID = value;
BrokenRules.Assert("ForeignIDRequired","Error.Object.RequiredFieldEmpty,IntegrationMap.Label.ForeignID","ForeignID",value.Length==0);
BrokenRules.Assert("ForeignIDLength",
"Error.Object.FieldLengthExceeded255,IntegrationMap.Label.ForeignID","ForeignID",value.Length>255);
MarkDirty();
}
}
}
}
/// <summary>
/// Set/get Integration object's name
/// 255 unicode characters max
/// </summary>
public string Name
{
get
{
return mName;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if(mName!=value)
{
mName = value;
BrokenRules.Assert("NameLength",
"Error.Object.FieldLengthExceeded255,IntegrationMap.Label.Name","Name",value.Length>255);
MarkDirty();
}
}
}
}
/// <summary>
/// DateTime field indicating the last time integration object was synchronized
/// Set by the integrating application.
///
/// Implementers may use this date as required, it's purpose is to aid in
/// synchronization and use is optional
///
/// If a null or non existant date is desired set this value to
/// System.DateTime.MinValue as that is the standard used in AyaNova for null dates
///
/// </summary>
public DateTime LastSync
{
get
{
return mLastSync.Date;
}
set
{
if (bReadOnly)
ThrowSetError();
else
{
if (mLastSync.Date != value)
{
mLastSync.Date = value;
MarkDirty();
}
}
}
}
/// <summary>
/// Object for use by integration application store
/// with individual map object
///
/// You can store any data you wish in this object, it is
/// serialized to and from the database in a binary blob / image field.
///
/// Typically this would be used to store data about an individual mapped object that is
/// application specific I.E. create a serializable class or structure to contain
/// data and store / retrieve via this field.
///
/// Don't go overboard with this object it *is* stored in the database and
/// should not be used to store huge binary objects, this will
/// only slow down your application and bloat the users database un-necessarily.
///
/// 32k or less is a good rule of thumb
///
/// We may enforce this to 32k or less in future so consider carefully keeping under the
/// 32K limit. If you need to go over this limit regularly then those
/// objects should be stored with the application that is integrating
/// outside of AyaNova. I.E. in a separate database or file system.
///
/// </summary>
public object MapObject
{
get
{
return mMapObject;
}
set
{
if (bReadOnly)
ThrowSetError();
else
{
if (mMapObject != value)
{
mMapObject = value;
MarkDirty();
}
}
}
}
/// <summary>
/// Set/get Integration object's AyaNovaCheckSum
/// 255 ascii characters max
///
/// This is an optional field that can be used to store
/// a checksum or any string value. It's intended use
/// is to store a checksum of the fields in the AyaNova
/// object that are of interest if they are changed.
///
/// So, for example, if you were interested in knowing if
/// an AyaNova object had a specific set of fields changed
/// since originally being added to this collection
/// you might generate a checksum on the
/// fields in question and store it here, then you can later
/// regenerate a checksum on that object and compare it to this
/// value to determine quickly if any of the fields of interest
/// have changed.
///
/// If you just want to know if any part of the object was changed
/// then you would normally track the Modified date of the AyaNova object
/// and compare it with the lastsync date here, this field is intended
/// to give more granular control if you are interested only in specific
/// fields that might have changed.
///
/// This could also be useful for comparing objects to see if a select
/// set of fields are identical
/// </summary>
public string AyaNovaCheckSum
{
get
{
return mAyaNovaCheckSum;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if(mAyaNovaCheckSum!=value)
{
mAyaNovaCheckSum = value;
BrokenRules.Assert("AyaNovaCheckSumLength",
"Error.Object.FieldLengthExceeded255,IntegrationMap.Label.AyaNovaCheckSum","AyaNovaCheckSum",value.Length>255);
MarkDirty();
}
}
}
}
/// <summary>
/// Set/get Integration object's ForeignCheckSum
/// 255 ascii characters max
///
/// This is an optional field that can be used to store
/// a checksum or any string value. It's intended use
/// is to store a checksum of the fields in the Foreign
/// object that are of interest if they are changed since
/// the point they were originally linked but you don't want
/// to track any changes to the object, only specific ones
/// to a limited set of data.
///
/// (for a more general change tracking method you might compare
/// the last sync date instead)
///
/// This could also be useful for comparing objects to see if a select
/// set of fields are identical
///
/// </summary>
public string ForeignCheckSum
{
get
{
return mForeignCheckSum;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if(mForeignCheckSum!=value)
{
mForeignCheckSum = value;
BrokenRules.Assert("ForeignCheckSumLength",
"Error.Object.FieldLengthExceeded255,IntegrationMap.Label.ForeignCheckSum","ForeignCheckSum",value.Length>255);
MarkDirty();
}
}
}
}
/// <summary>
/// Throw an error when a read only user
/// tries to set a property
/// (this should normally never be called unless someone is using the developer api since the UI
/// should prevent it from happening initially)
/// </summary>
private void ThrowSetError()
{
throw new System.Security.SecurityException
(
string.Format
(
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToChange"),
LocalizedTextTable.GetLocalizedTextDirect("O.IntegrationMap")
)
);
}
#endregion
#region System.object overrides
/// <summary>
///
/// </summary>
/// <returns></returns>
public override string ToString()
{
return "IntegrationMap" + mID.ToString();
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(Object obj)
{
if ( obj == null || GetType ( ) != obj.GetType ( ) ) return false;
IntegrationMap c=(IntegrationMap)obj;
return mID==c.mID;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return ("IntegrationMap" + mID).GetHashCode();
}
#endregion
#region Static methods
/// <summary>
/// Create item
/// Create a new integration map child object
/// </summary>
/// <param name="obj">Parent Integration object </param>
/// <returns>New Item</returns>
internal static IntegrationMap NewItem(Integration obj)
{
// if(AyaBizUtils.Right("Object.IntegrationMap")>(int)SecurityLevelTypes.ReadOnly)
// {
IntegrationMap child=new IntegrationMap();
child.mIntegrationID=obj.ID;
return child;
// }
// else
// throw new System.Security.SecurityException(
// string.Format(
// LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToCreate"),
// LocalizedTextTable.GetLocalizedTextDirect("O.IntegrationMap")));
//
}
/// <summary>
/// Retrieve item
/// </summary>
/// <param name="dr">Data reader</param>
/// <returns>item from database</returns>
internal static IntegrationMap GetItem(SafeDataReader dr)
{
// if(AyaBizUtils.Right("Object.IntegrationMap")>(int)SecurityLevelTypes.NoAccess)
// {
IntegrationMap child = new IntegrationMap();
child.Fetch(dr);
return child;
// }
// else
// throw new System.Security.SecurityException(
// string.Format(
// LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToRetrieve"),
// LocalizedTextTable.GetLocalizedTextDirect("O.IntegrationMap")));
}
#endregion
#region DAL DATA ACCESS
/// <summary>
/// Fetch from db
/// </summary>
/// <param name="dr"></param>
private void Fetch(SafeDataReader dr)
{
//Standard items
mCreated=DBUtil.ToLocal(dr.GetSmartDate("aCreated"));
mCreator=dr.GetGuid("aCreator");
mModified=DBUtil.ToLocal(dr.GetSmartDate("aModified"));
mModifier=dr.GetGuid("aModifier");
//IntegrationMap specific parameters
mID=dr.GetGuid("aID");
mIntegrationID=dr.GetGuid("aIntegrationID");
RootObjectID=dr.GetGuid("aRootObjectID");
RootObjectType=(RootObjectTypes)dr.GetInt16("aRootObjectType");
ForeignID=dr.GetString("aForeignID");
Name=dr.GetString("aName");
mLastSync=DBUtil.ToLocal(dr.GetSmartDate("aLastSync"));
//Get the MapObject
//Get the layout size
int mMapObjectSize = dr.GetInt32("aMapObjectSize");
//Is there anything to load?
if (mMapObjectSize > 0)
{
BinaryFormatter bformatter = new BinaryFormatter();
bformatter.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
byte[] obData = new Byte[mMapObjectSize];
//retrieve the bytes
dr.GetBytes("aMapObject", 0, obData, 0, mMapObjectSize);
MemoryStream mstream = new MemoryStream(obData);
this.mMapObject = (object)bformatter.Deserialize(mstream);
}
else
this.mMapObject = null;
//Get access rights level
//bReadOnly=AyaBizUtils.Right("Object.IntegrationMap")<(int)SecurityLevelTypes.ReadWrite;
MarkOld();
}
/// <summary>
/// Persist object to database
/// </summary>
/// <param name="obj">Parent integratin object</param>
/// <param name="tr">Parents transaction object</param>
internal void Update(Integration obj,IDbTransaction tr)
{
//No need to update if there is nothing changed
if(!this.IsDirty) return;
//get modification time temporarily, if update succeeds then
//set to this time
System.DateTime dtModified = DBUtil.CurrentWorkingDateTime;
// If not a new record, check if record was modified
//by another user since original retrieval:
if(!IsNew)
DBUtil.CheckSafeToUpdate(this.mModified.Date,this.mID,"aIntegrationMap");
#region Delete
if(IsDeleted)
{
if(!IsNew)
{
//Delete
DBCommandWrapper cmDelete = DBUtil.GetCommandFromSQL("DELETE FROM aIntegrationMap WHERE aID = @ID;");
cmDelete.AddInParameter("@ID",DbType.Guid,this.mID);
DBUtil.DB.ExecuteNonQuery(cmDelete, tr);
}
MarkNew();
return;
}
#endregion
#region Add / Update
DBCommandWrapper cm = null;
if(IsNew)//Add or update?
cm=DBUtil.GetCommandFromSQL(
"INSERT INTO aIntegrationMap (aRootObjectID, aRootObjectType, aIntegrationID, aForeignID, " +
"aName, aMapObjectSize, aMapObject, " +
"aLastSync,aID, aCreated, aModified, aCreator, aModifier) " +
"VALUES (@RootObjectID,@RootObjectType, @IntegrationID,@ForeignID, " +
"@Name, @MapObjectSize, @MapObject, " +
"@LastSync, @ID, @Created, @Modified, @CurrentUserID,@CurrentUserID)"
);
else
cm=DBUtil.GetCommandFromSQL(
"UPDATE aIntegrationMap SET " +
"aRootObjectID=@RootObjectID,aRootObjectType=@RootObjectType, aIntegrationID=@IntegrationID,aForeignID=@ForeignID, " +
"aName=@Name, aMapObjectSize=@MapObjectSize, aMapObject=@MapObject, " +
"aLastSync=@LastSync, aModifier = @CurrentUserID, " +
"aModified=@Modified WHERE aID=@ID"
);
//IntegrationMap fields
cm.AddInParameter("@ID",DbType.Guid,mID);
cm.AddInParameter("@IntegrationID",DbType.Guid,mIntegrationID);
cm.AddInParameter("@RootObjectID",DbType.Guid,mRootObjectID);
cm.AddInParameter("@RootObjectType",DbType.Int16,(int)mRootObjectType);
cm.AddInParameter("@ForeignID",DbType.String,mForeignID);
cm.AddInParameter("@Name",DbType.String,mName);
cm.AddInParameter("@LastSync",DbType.DateTime,DBUtil.ToUTC(mLastSync).DBValue);
//MapObject serialize:
if (mMapObject != null)
{
MemoryStream ms = new MemoryStream();
BinaryFormatter b = new BinaryFormatter();
b.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
b.Serialize(ms, mMapObject);
cm.AddInParameter("@MapObjectSize", DbType.Int32, ms.Length);
cm.AddInParameter("@MapObject", DbType.Object, ms.GetBuffer());
}
else
{
cm.AddInParameter("@MapObjectSize", DbType.Int32, 0);
cm.AddInParameter("@MapObject", DbType.Object, new byte[1]);
}
//Standard fields
cm.AddInParameter("@CurrentUserID",DbType.Guid, CurrentUserID);
cm.AddInParameter("@Created",DbType.DateTime, DBUtil.ToUTC(mCreated.Date));
cm.AddInParameter("@Modified",DbType.DateTime, DBUtil.ToUTC(dtModified));
DBUtil.DB.ExecuteNonQuery(cm, tr);
MarkOld();//db is now synched with object
//Successful update so
//change modification time to match
this.mModified.Date=dtModified;
#endregion
}
#endregion
}//end IntegrationMap
}//end namespace GZTW.AyaNova.BLL