Files
ayanova7/source/bizobjects/AyaLib/GZTW.AyaNova.BLL/AyaBizUtils.cs
2019-10-07 21:43:30 +00:00

5270 lines
203 KiB
C#
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Data;
using System.IO;
using System.Globalization;
using System.ComponentModel;
using System.Reflection;
using CSLA.Security;
using System.Threading;
using System.Runtime.Serialization;
using GZTW.Profile;
using GZTW.Data;
using System.Collections.Generic;
using System.IO.Compression;
namespace GZTW.AyaNova.BLL
{
#region Custom exceptions
#pragma warning disable 1591
#region TrialException
[Serializable]
public class TrialException : ApplicationException
{
// Normal 3 constructors
public TrialException()
{
}
public TrialException(string message)
: base(message)
{
}
public TrialException(string message, Exception inner) :
base(message, inner)
{
}
// deserialization constructor
public TrialException(SerializationInfo info,
StreamingContext context) :
base(info, context)
{
}
}
#endregion
#region FetchException
/// <summary>
/// This exception is thrown when a attempt is made to
/// retrieve an item from the database that doesn't exist
/// </summary>
[Serializable]
public class FetchException : ApplicationException
{
/// <summary>
///
/// </summary>
public FetchException()
{
}
/// <summary>
///
/// </summary>
/// <param name="message"></param>
public FetchException(string message)
: base(message)
{
}
/// <summary>
///
/// </summary>
/// <param name="message"></param>
/// <param name="inner"></param>
public FetchException(string message, Exception inner) :
base(message, inner)
{
}
/// <summary>
/// deserialization constructor
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
public FetchException(SerializationInfo info,
StreamingContext context) :
base(info, context)
{
}
}
#endregion
#region AyConcurrencyException
/// <summary>
/// This exception is thrown when a attempt is made to
/// save an object that has been modified by someone else
/// between the point it was loaded for editing and then saved
/// </summary>
[Serializable]
public class AyConcurrencyException : ApplicationException
{
/// <summary>
///
/// </summary>
public AyConcurrencyException()
{
}
/// <summary>
///
/// </summary>
/// <param name="message"></param>
public AyConcurrencyException(string message)
: base(message)
{
}
/// <summary>
///
/// </summary>
/// <param name="message"></param>
/// <param name="inner"></param>
public AyConcurrencyException(string message, Exception inner)
:
base(message, inner)
{
}
/// <summary>
/// deserialization constructor
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
public AyConcurrencyException(SerializationInfo info,
StreamingContext context)
:
base(info, context)
{
}
}
#endregion
#region AyAyaFileTooLargeException
/// <summary>
/// This exception is thrown when a attempt is made to
/// save a file to the AyaNova database that is larger than the
/// default limit or larger than the admin set limit in global settings
/// (default limit is 50mb)
/// </summary>
[Serializable]
public class AyAyaFileTooLargeException : ApplicationException//case 73
{
/// <summary>
///
/// </summary>
public AyAyaFileTooLargeException()
{
}
/// <summary>
///
/// </summary>
/// <param name="message"></param>
public AyAyaFileTooLargeException(string message)
: base(message)
{
}
/// <summary>
///
/// </summary>
/// <param name="message"></param>
/// <param name="inner"></param>
public AyAyaFileTooLargeException(string message, Exception inner)
:
base(message, inner)
{
}
/// <summary>
///
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
public AyAyaFileTooLargeException(SerializationInfo info,
StreamingContext context)
:
base(info, context)
{
}
}
#endregion
#region LiteDBTypeInvalidException
[Serializable]
public class LiteDBTypeInvalidException : ApplicationException
{
// Normal 3 constructors
public LiteDBTypeInvalidException()
{
}
public LiteDBTypeInvalidException(string message)
: base(message)
{
}
public LiteDBTypeInvalidException(string message, Exception inner) :
base(message, inner)
{
}
// deserialization constructor
public LiteDBTypeInvalidException(SerializationInfo info,
StreamingContext context) :
base(info, context)
{
}
}
#endregion
#region AyNotSubscribedForThisVersionException
[Serializable]
public class AyNotSubscribedForThisVersionException : ApplicationException
{
// Normal 3 constructors
public AyNotSubscribedForThisVersionException()
{
}
public AyNotSubscribedForThisVersionException(string message)
: base(message)
{
}
public AyNotSubscribedForThisVersionException(string message, Exception inner) :
base(message, inner)
{
}
// deserialization constructor
public AyNotSubscribedForThisVersionException(SerializationInfo info,
StreamingContext context) :
base(info, context)
{
}
}
#endregion
#region AySchemaOutDatedException
[Serializable]
public class AySchemaOutDatedException : ApplicationException
{
// Normal 3 constructors
public AySchemaOutDatedException()
{
}
public AySchemaOutDatedException(string message)
: base(message)
{
}
public AySchemaOutDatedException(string message, Exception inner) :
base(message, inner)
{
}
// deserialization constructor
public AySchemaOutDatedException(SerializationInfo info,
StreamingContext context) :
base(info, context)
{
}
}
#endregion
#pragma warning restore 1591
#endregion custom exceptions
/// <summary>
/// Utility functions and configuration connection data
/// </summary>
public sealed class AyaBizUtils
{
#region class variables
// Create a logger for use in this class
//private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//private static bool _Initialized=false;
/// <summary>
/// Contains DataPortal diagnostic info if applicable
/// </summary>
public static string PortalDiagnostics = "";
/// <summary>
///
/// </summary>
public static Global mGlobalSettings = null;
/// <summary>
///
/// </summary>
internal static GlobalEx _GlobalX = null;
internal static bool _AllowAutomaticClosedWorkorderStatus = true;
/// <summary>
/// Set to false to prevent workorder service status to be set
/// automatically to global default when work order is closed.
///
/// This property is used by AyaNovaQBI, AyaNovaPTI and AyaImport
/// which all need to set the status explicitly.
/// </summary>
public static bool AllowAutomaticClosedWorkorderStatus
{
get
{
return _AllowAutomaticClosedWorkorderStatus;
}
set
{
_AllowAutomaticClosedWorkorderStatus = value;
}
}
internal static bool _AllowAutomaticMRUOnUpdate = true;
/// <summary>
/// Set to false to prevent objects being added to the MRU
/// Most recently used list when an object is updated
///
/// This property is used by AyaNovaQBI, AyaNovaPTI and AyaImport
/// which all need to import large volumes of objects in one go
/// and adding to MRU would slow down the import unnecessarily
/// </summary>
public static bool AllowAutomaticMRUOnUpdate
{
get
{
return _AllowAutomaticMRUOnUpdate;
}
set
{
_AllowAutomaticMRUOnUpdate = value;
}
}
//case 535
internal static UserMRUs _mru = null;
/// <summary>
/// Current thread user's most recently used AyaNova object list
/// <seealso cref="UserMRUs"/>
/// </summary>
public static UserMRUs MRU
{
get
{
//never cache if it's a dp connection case 768
//this is required because normally ayanova will use this as a cache to save time
//however when going through a dataportal the updates are not done on the same mru
//object as we see here cached so the cache can't be used when dataportaling but we don't
//want to give up on caching for the rest of the users so it's done like this
//slightly different check for portal method because here we're we might be calling from the client
//and so we're not in the portal so we can't use atdataportalserver method
//but that's ok because we know what connection settings were...
if (AyaNovaConnectionSetting.UsingDataPortal)
_mru = null;
//when we're calling from the portal it's using a direct connection so it will use it's own version, however
//it's likely null to begin with in most cases so it will retrieve fresh or in rare cases re-use.
//either way Bob's your lobster.
if (_mru == null)
_mru = UserMRUs.GetItems(User.CurrentThreadUserID);
return _mru;
}
set
{
//No matter what it's set to it resets it to null
_mru = null;
}
}
//case 768
/// <summary>
/// True if the currently executing code is running from
/// within a data portal server
/// </summary>
internal static bool AtDataPortalServer
{
get
{
return Assembly.GetEntryAssembly() == null;//A DataPortal doesn't have an entry assembly
}
}
/// <summary>
/// Active session Global settings object
/// API users - To ensure you are using the most up to date global settings object
/// use this one instead of retrieving your own <see cref="Global"/>
/// </summary>
public static Global GlobalSettings
{
get
{
if (mGlobalSettings == null)
mGlobalSettings = Global.GetItem();
return mGlobalSettings;
}
set
{
mGlobalSettings = null;//case 786
}
}
internal static GlobalEx GlobalX
{
get
{
if (_GlobalX == null)
_GlobalX = GlobalEx.GetItem();
return _GlobalX;
}
}
//case 2099 - need to see the schema from the UI
/// <summary>
/// Database schema version - used internally
/// </summary>
public static int DBSChemaVersion
{
get
{
return GlobalX.DBSchemaVersion;
}
}
private static LocalizedTextTable mLocaleText = null;
/// <summary>
/// Cached <see cref="LocalizedTextTable"/> for current user.
/// API users should use this rather than instantiating a LocalizedTextTable directly for performance reasons
/// </summary>
public static LocalizedTextTable LocaleText
{
get
{
if (mLocaleText == null && Thread.CurrentPrincipal.Identity.IsAuthenticated)
mLocaleText = LocalizedTextTable.Load(((BusinessPrincipal)Thread.CurrentPrincipal).Language);
return mLocaleText;
}
set
{
mLocaleText = null;
}
}
//case 1163
/// <summary>
/// Check if time zone has been overridden for current thread user
/// <seealso cref="TimeZoneOffset"/>
/// </summary>
public static bool OverrideTimeZone
{
get
{
return ((BusinessPrincipal)Thread.CurrentPrincipal).OverrideTimeZone;
}
}
/// <summary>
/// Actual offset from GMT / UTC if time zone has been overridden
/// <seealso cref="OverrideTimeZone"/>
/// </summary>
public static double TimeZoneOffset
{
get
{
return ((BusinessPrincipal)Thread.CurrentPrincipal).TimeZoneOffset;
}
}
private static AyaNovaConnectionSettings _AyaNovaConnectionSetting = null;
/// <summary>
/// This is the connection setting used by the AyaNova session.
/// If it is not set explicitly (default behaviour) it will
/// retrieve the connection settings from the config.txt file
/// residing in the same folder as this assembly.
///
/// A caller can set this explicitly in order to avoid the use of the config.txt file
/// (handy in situations where more than one database needs to be logged into separately)
///
/// If a caller sets this property explicitly note that the session is logged out automatically
/// </summary>
public static AyaNovaConnectionSettings AyaNovaConnectionSetting
{
get
{
if (_AyaNovaConnectionSetting == null)
{
_AyaNovaConnectionSetting = new AyaNovaConnectionSettings();
_AyaNovaConnectionSetting.GetConnectionData();
}
return _AyaNovaConnectionSetting;
}
set//case 944
{
//Ensure that the authentication in the principle doesn't survive a change of connection string
//this way a person can't login to one database, change the connection and keep working as if authenticated
//in the new database
if (Thread.CurrentPrincipal != null) Thread.CurrentPrincipal = null;
_AyaNovaConnectionSetting = value;
Initialize();
}
}
/// <summary>
///
/// </summary>
public static GZTW.AyaNova.BLL.Region RegionalSettings = null;
internal static string _CallerSig;
internal static string _Caller;
//If this value is true then CE import program has
//requested an override of normal license checking in order
//to add scheduled users to the workorders who may not be active
//right now
internal static bool _CE = false;
//This is true while the schema is updating
//this overrides security temporarily so
//that the schema can be updated
internal static bool _SchemaUpdating = false;
/// <summary>
/// AyaNova conforms to the "Semantic versioning" scheme, see here: http://semver.org/
/// This property is equivalent to the "Patch" version of semantic versioning schema
/// and is stored in the assemblies file version info stored on disk so it can be
/// examined in Windows Explorer or in the UI of any of the AyaNova provided assemblies
///
/// </summary>
public static string SubVersion
{
get
{
//Note: this should either be an empty string or
//an identifier that starts with a tab and ends with a cr/lf
//as it's munged into the support info
//return "\t*** Business object assembly (GZTW.AyaNova.BLL.dll) Sub Version: 0 ***\r\n";
StringBuilder sb = new StringBuilder();
Assembly a = Assembly.GetExecutingAssembly();
System.Diagnostics.FileVersionInfo fileVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(a.Location);
sb.Append("\tBusiness object assembly: " + System.IO.Path.GetFileName(fileVersion.FileName) + " ");
sb.Append(DisplayVersion(a.GetName().Version));
//case 2003
int nHotFix = fileVersion.FileBuildPart;
//int nHotFix = fileVersion.FileBuildPart;
if (nHotFix > 0)
sb.Append(" (Patch " + nHotFix.ToString() + ")");
//case 2094
sb.Append(" (Built ");
sb.Append(GZTW.AyaNova.BLL.Timestamp.BuildAt.ToString());
sb.Append(")");
sb.Append("\r\n");
return sb.ToString();
}
}
///// <summary>
///// *** DEPRECATED AND NOT USED, WILL ALWAYS BE ZERO ***
///// </summary>
//public static string SubVersionShort
//{
// get
// {
// return "0";
// }
//}
/// <summary>
/// Universal Guid to indicate that instead of instantiating an existing
/// object a new one should be created with it's own id
///
/// Used by the AyaNova UI layer to indicate when opening an object for editing if it
/// should be created first. If this ID is used instead of an actual id then
/// the UI utility class knows to create the object as new instead of opening an
/// existing one
/// </summary>
[Browsable(false)]
public static Guid NewObjectGuid
{
get
{
return new Guid("{8D6624C7-3E70-48cf-9C0F-629FB70242EE}");
}
}
/// <summary>
/// Universal Guid to indicate that a select is intended to refresh a list
/// not be the selected item in the list
///
/// Used by the AyaNova UI layer trigger a refresh in a list on command
/// </summary>
[Browsable(false)]
public static Guid RefreshGuid
{//case 105
get
{
return new Guid("{305E645D-DBD4-4466-8A61-AB83E46BF5C3}");
}
}
//case 2094
//This flag will cause all rights to be read only
//and is intended where there is something in PFC preventing AyaNova from running
//like mismatch of license and version or schema needs update from AyaNova windows
//etc. These all throw exceptions but people could have their own code that
//they use that eats the exceptions and so they could just keep using their code
//potentially causing issues
internal static bool LockDown = false;
#endregion
#region AyaNova CE import override
/// <summary>
///
/// </summary>
[Browsable(false)]
public static bool CE
{
set
{
//Only allow this to be set by a calling assembly signed with our own strong name key
if (_CallerSig == "DF-66-A8-D8-E4-98-33-D3")
_CE = value;
}
}
#endregion
#region MAIN INIT entry point for biz object library
/// <summary>
/// Initialization and pre-flight check of the AyaNova DB connection
/// </summary>
/// <example>
/// Initializing AyaNova business object library in preparation for logging in:
/// <code>
/// //The call to Initialize is always the first required in any
/// //Stand alone application working with AyaNova (not required for plugins), it initializes the database
/// //connection and business object framework and confirms operations can
/// //take place
///
/// //IMPORTANT: If you receive an exception when calling the Initialize method it is most likely
/// //a connection string problem in your config.txt file causing the
/// //database provider to throw a not found exception. Or a problem with the configuration
/// //file itself like it's missing or not configured properly.
///
/// //Remember that in the case of any exception using the AyaNova business object library
/// //it is that exception's Inner exception which is most likely the actual error (if present)
/// //because AyaNova objects are invoked through a factory method which wraps any actual exception
/// //generated by the business object inside a TargeInvocationException
///
/// try
/// {
/// GZTW.AyaNova.BLL.AyaBizUtils.Initialize();
/// }
/// catch (Exception ex)
/// {
/// //"crack" the exception to get to the innermost exception
/// while (ex.InnerException != null)
/// ex = ex.InnerException;
///
/// MessageBox.Show(ex.Message);
/// return;
/// }
///
///
/// //Once your application gets to this point right after Initialize without error
/// //you can be assured that you have a clean configuration file and a connection
/// //to the database and are ready to log in
///
/// </code>
/// </example>
public static void Initialize()
{
//_Initialized=false;
//track who is calling for security purposes
//i.e. allowing importing workorders from ce to
//select non-active techs etc
if (Assembly.GetEntryAssembly() != null)//A DataPortal doesn't have an entry assembly
{
_Caller = Assembly.GetEntryAssembly().GetName().Name;
if (Assembly.GetEntryAssembly().GetName().GetPublicKeyToken() == null)
_CallerSig = "";
else
_CallerSig = BitConverter.ToString(Assembly.GetEntryAssembly().GetName().GetPublicKeyToken());
}
else//case 2094
{
_Caller = "DP";
_CallerSig = "DP";
}
//Any apps signed with the AyaNova.snk key have this sig: "DF-66-A8-D8-E4-98-33-D3"
//attempt to connect to database
if (!CheckDataAvailable()) return;
////case 1039 //log.Debug("Initialize() - Business logic tier initialized OK");
//_Initialized=true;
}
#endregion
#region Validation pre-flight checks: License, Date, DB engine, DB Schema, subscription
private static bool CheckDataAvailable()
{
//do a fake login to get business principle set
Login("abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz");
#region Validate server date makes sense
//case 2094
//Confirm date is ok at server
bool dtOk = DBDtPfc.CheckIt();
if (!dtOk)
{
LockDown = true;
////"Error: There appears to be a problem with the date on the server.\r\nTo protect your data integrity AyaNova will not run until this issue is fixed.";
throw new System.ApplicationException(Ec("\0\a\n&HU1<\a\0t1\atE6Ut\a\n6\bt<R\r1R U\n:R\r1R\0&z1;R; R\f\n!\0U5E=\03\0-R45<5R\f8U\v;U!U:\tt\f'R'\aE=U=\nz", "True"));
}
#endregion
//Gather this info at this point
//used by WBI and winform App
PortalDiagnostics = DataPortalInfo.GetItem();
//fetch the license key settings object
_GlobalX = GlobalEx.GetItem();
#region Validate license key is not revoked
//Case 508
//Note: DigestValue is the ID value for JSON keys
//so use the ID value instead to revoke a JSON KEY
switch (_GlobalX.DigestValue)
{
#region Case 428
//<RegisteredTo>Braintek</RegisteredTo>,
case "mpBdutEgT9w8hWT/T1uwNmLGeLQ=":
//<RegisteredTo>MCCAIN RESEARCH LAB , INC</RegisteredTo>,
case "2pYzGIlMU18QomByUC4D72ViOyE=":
//<RegisteredTo>Standby Power System Consultants, Inc.</RegisteredTo>,
case "PlzMfZoVI4iR0Ws11yqaAf+4g5U=":
//<RegisteredTo>Snyder Services</RegisteredTo>,
case "EMmFEcwm78pskcWAIZ7z5CKdOxk=":
#endregion
#region Case 874
//<RegisteredTo>Vrobel's Heating & Cooling</RegisteredTo>,
case "dhkBn04QOYxysTnXTql/9VHkEtI=":
#endregion
#region Case 1167
//<RegisteredTo>Verhoeven kantoortotaal</RegisteredTo>
case "b75SpAQzm71JsRLNtosk0ty1Tsw=":
#endregion
#region Case 1191
// <RegisteredTo>CF Can Group</RegisteredTo>
case "i9/LC/6RVsoIT1X5YKlzBRA2T08=":
#endregion
#region Case 1364
// <RegisteredTo>Leavenworth County</RegisteredTo>
case "W2inW3VDw8FPzMdBHgE8k+U6gSg=":
// <RegisteredTo>mbernardinelli</RegisteredTo>
case "13OUStnOVvlJszgrUIcVxMcLkhw=":
// <RegisteredTo>Penney Lawn Service</RegisteredTo>
case "OSQOreX+pT0TczLrxb6ucOv4rF8=":
#endregion
#region Case 1862
// <RegisteredTo>Morris Waterworks</RegisteredTo>
case "8lPDmvrFCHnVxUDGzscSZKmGtgM=":
#endregion
#region Case 3291
// "RegisteredTo": "Preferred Medical Systems"
//sent key then asked to cancel
case "1496793532":
#endregion
#region Case 3517
// "RegisteredTo": "The Underground Sprinkler Co"
//sent key then asked to cancel - VERY SKETCHY CUSTOMER
case "1507851308":
#endregion
LockDown = true;
throw new ApplicationException("\r\n\r\n***************\r\n\r\n\r\nFATAL ERROR 42 - EMAIL THE FOLLOWING INFORMATION TO\r\nSUPPORT@AYANOVA.COM IMMEDIATELY:\r\n\r\nError code: [" + _GlobalX.DigestValue + "]\r\n\r\n\r\n********************\r\n\r\n");
}
if (_GlobalX.RegisteredTo == "DEVELOPMENT")
{
LockDown = true;
throw new ApplicationException("\r\n**** INVALID (TEST) DATABASE ****\r\nPlease contact AyaNova technical support for a replacement trial database.\r\n");
}
#endregion
#region Validate database engine is supported
//case 530 ensure db engine is young enough
DBInfo dbi = DBInfo.GetInfo();
string dbOutOfDateExceptionMessage = "Error: Your database server version could not be determined / is out of date.\r\n" +
"As detailed in the documentation: AyaNova requires either Microsoft SQL Server 2005 or newer\r\n" +
"or FireBird server / embedded version 2.11 or newer.\r\n";
if (dbi.Version.StartsWith("Error:"))
{
LockDown = true;
throw new System.NotSupportedException(dbOutOfDateExceptionMessage);
}
if (dbi.DBServerType == "MSSQL")
{
if (dbi.Version.StartsWith("2000"))
{
LockDown = true;
throw new System.NotSupportedException(dbOutOfDateExceptionMessage);
}
//any older version would have thrown an exception above because only 2000 up supports the method used to get the version
}
else if (dbi.DBServerType == "FireBird")
{
if (dbi.Version == "2.1")
{
LockDown = true;
throw new System.NotSupportedException(dbOutOfDateExceptionMessage);
}
}
if (Lite && !AyaNovaConnectionSetting.SingleUserConnection)
{
LockDown = true;
throw new LiteDBTypeInvalidException();
}
#endregion
#region Validate this assembly is not too old for this DB Schema
//Ensure schema matches required version
//All schema related code in DBManager object
//Case 408 changed wording slightly to be less ambiguous
if (GlobalX.DBSchemaVersion > DBManager.RequiredSchema)
{
LockDown = true;
throw new System.PlatformNotSupportedException
(
string.Format
(
"\r\n************************************************\r\n" +
"This program requires database schema version {0}\r\n " +
"The current database schema is version {1}\r\n" +
"(In other words: this program is outdated and needs to be upgraded)\r\n" +
"************************************************\r\n",
DBManager.RequiredSchema.ToString(),
GlobalX.DBSchemaVersion.ToString()
)
);
}
#endregion
#region Validate DB Schema has not been tampered with
//case 2094
//Only check the fingerprint if the db schema matches
//because the schema may be updated later with some changes
//recently made for this case
if (GlobalX.DBSchemaVersion == DBManager.RequiredSchema)
{
//Case 856
//check the schema fingerprint to detect tampering
string schema = dbi.FingerPrint;
//case 1104
//Danish AA bug rears it's head again
//If user has Danish or some other languages set then
//the code that brings out the fingerprint treats AA together as a special single character
//which affects the hash
//As a safer alternative we'll count the number of tables and columns instead
//as the user can't rename them without breaking ayanova anyway and this will still
//catch the intended purpose of people adding columns or tables
//To do this we'll count \r\n combinations because every table and column name ends with that
//in any type of db in the db layer code
Regex rxCountLines = new Regex(
"\\r\\n",
RegexOptions.IgnoreCase
| RegexOptions.Multiline
| RegexOptions.Compiled
);
int nSchemaCount = rxCountLines.Matches(schema).Count;
//SHA256 shaM = new SHA256Managed();
//UTF8Encoding enc = new UTF8Encoding();
//string shash = BitConverter.ToString(shaM.ComputeHash(enc.GetBytes(schema))).Replace("-", "");
if (nSchemaCount != 1406)
{
//case 1142, apparently if it's sql2000 they can get this as well so adjusting error message
//schema is not clean
LockDown = true;
throw new System.Security.SecurityException(
"This AyaNova database appears to have been modified outside of the AyaNova program or is damaged in some way.\r\n" +
"This may very rarely be caused by corruption but is more likely a result of someone tampering with\r\n" +
"the database and making changes outside the AyaNova program.\r\n\r\n" +
"(In some cases you may get this error when attempting to use AyaNova 5.x or newer with Microsoft SQL server 2000\r\n" +
"which is not supported, only version 2005 or newer.)\r\n\r\n" +
"Your data is probably ok, but the database is not in a supportable state and will need to be returned to it's proper state.\r\n" +
"Please provide the following information to AyaNova technical support for assistance:\r\n\r\n" + "Schema Count: " + nSchemaCount.ToString() + "\r\nSchema:\r\n" + schema);
}
}
#endregion FingerPrint
#region Validate a subscription license is present
string sNoSub = "This is a new version of AyaNova not previously used with this database\r\n\r\nAn active subscription license is required to use it\r\n\r\nThere are two options:\r\n1) Downgrade back to the previous version\r\n2) Install a new license\r\n\r\n";
//If it's not a subscription license it's definitely not allowed to use this build
//any new releases post May 1 2016 require a subscription license.
if (!GlobalX.SubscriptionLicense)
{
LockDown = true;
throw new AyNotSubscribedForThisVersionException
(
string.Format
(
"\r\n" +
"*************************************************************\r\n\r\n" +
"Subscription license not found!\r\n\r\n" +
sNoSub +
"Contact support@ayanova.com for more information\r\n" +
"*************************************************************\r\n\r\n"
)
);
}
#endregion
#region Validate subscription allows this build date of biz object library
// if the subscription has expired and it was built after the subsription expired
//then throw the exception
if ((GlobalX.SubscriptionExpired && (Timestamp.BuildAt > ExpiryDate)))
{
LockDown = true;
throw new AyNotSubscribedForThisVersionException
(
string.Format
(
"\r\n*************************************************************\r\n" +
sNoSub +
"Your subscription license expired on {0}\r\n" +
"Please purchase a new subscription\r\n" +
"*************************************************************\r\n",
GlobalX.ExpiryDate.ToLongDateString()
)
);
}
#endregion
#region Validate schema is not outdated with non winform ayanova calling assembly
//TODO: throw if outdated schema and caller is not winform AyaNova.
if (SchemaOutdated && _Caller != "AyaNova")
{
LockDown = true;
throw new AySchemaOutDatedException
(
string.Format
(
"\r\n" +
"****************************************************************\r\n\r\n" +
"The AyaNova database schema is outdated and needs to be adjusted\r\n" +
"to work with this version of this application\r\n\r\n" +
"Start AyaNova for Windows to upgrade the database schema now\r\n\r\n" +
"Contact support@ayanova.com if you need more information\r\n" +
"*************************************************************\r\n\r\n"
)
);
}
#endregion
#region TRIAL key first boot processing and NEW DB RELEASE trial date utility
//****************** Set first boot and eval data advancing date
#if(DEBUG)
//In a debug wrapper to be on the safe side
//*** NOTE: do not run this block until the target db has been opened at least once
//to forward the dates first otherwise it will be messed up. ***
//Uncomment this code
//set the dates accordingly
//(Should be the same date as the last time the db was opened to advance eval dates)
//run once
//shut down and recomment this code
//***************************************************************
//GlobalX.TData = new GZTW.AyaNova.BLL.GlobalEx.AGlobalExData();
//GlobalX.TData.EvalExpire = new DateTime(1968, 03, 12, 0, 0, 0, 0);
//GlobalX.TData.EvalAdvanceReference = new DateTime(2017, 12, 11, 0, 0, 0, 0);
//GlobalX.Save();
//System.Diagnostics.Debugger.Break();
//***********************************************************
//RECOMMENT THE ABOVE WHEN DONE
#endif
//****************************************************************
//Is it a trial first boot?
if (GlobalX.TData.EvalExpire == new DateTime(1968, 03, 12, 0, 0, 0, 0))
{
//it's a first boot
ProcessFirstBoot();
}
return true;
}
private static void ProcessFirstBoot()
{
System.DateTime dtAdvance = GlobalX.TData.EvalAdvanceReference;
//Gextest
GlobalX.TData = new GZTW.AyaNova.BLL.GlobalEx.AGlobalExData();
//case 3646 changed from 31 to 46 days
GlobalX.TData.EvalExpire = System.DateTime.Now.AddDays(46);
GlobalX.Save();
//Advance trial data dates
DBManager.AdvanceTrialDataDates(dtAdvance);
}
#endregion
#endregion
#region Schema update and outdated properties
//case 2094
/// <summary>
/// True if the current AyaNova database schema version is older than the
/// version required for this release of AyaNova
/// Used by UI to trigger update processing after manager login
/// </summary>
public static bool SchemaOutdated
{
get
{
return (GlobalX.DBSchemaVersion < DBManager.RequiredSchema);
}
}
//case 2094
//Update schema if necessary. This will only be called from the Winform UI
//NOTE: this can only be called after initialization and initialization checks
//that they have an active subscription so no need to check subscription status here.
/// <summary>
/// Do not call this, internal only
/// </summary>
/// <returns></returns>
[Browsable(false)]
public static bool UpdateSchema()
{
//Upgrade the database?
if (SchemaOutdated)
{
//flag schema as updating so that rights will
//temporarily return full access during schema update
//because some schema updates require access to various
//biz objects
_SchemaUpdating = true;
DBManager.UpdateSchema();
_SchemaUpdating = false;
return true;
}
return false;
}
#endregion
#region LOGIN
/// <summary>
/// Login to database.
/// This replaces the direct call to BusinessPrincipal.Login which has been deprecated
/// to allow for consolidated connnection settings.
///
/// This is a breaking change for v3.x api users
/// </summary>
/// <param name="Username">AyaNova login name</param>
/// <param name="Password">AyaNova login password</param>
/// <example>
/// After the call to Initialize() you're ready to login as follows:
/// <code>
/// //This is the default AyaNova trial login and password
/// //and this is how you login to AyaNova
/// AyaBizUtils.Login("manager","letmein");
///
/// //confirm the user is logged in:
/// if(Thread.CurrentPrincipal.Identity.IsAuthenticated==false)
/// {
/// //Nope, they are not authenticated so
/// //show an error and bail out
/// MessageBox.Show("Login failed");
/// return;
/// }
///
/// //At this point we're logged in an have access to the entire API within the rights of the logged in user
/// </code>
/// </example>
public static void Login(string Username, string Password)
{
//case 1172
if (Username != "abcdefghijklmnopqrstuvwxyz" && Password != "abcdefghijklmnopqrstuvwxyz")//ignore initial fake login
{
if (Lite)
{
//login as the default user only no matter what they're trying to do
Username = "user";
Password = "user";
}
}
BusinessPrincipal.Login(Username, Password, AyaNovaConnectionSetting);
////case 53 and other stuff down the road
// if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
// LocaleText = LocalizedTextTable.Load(((BusinessPrincipal)Thread.CurrentPrincipal).Language);
mLocaleText = null;
StopList = null;
//case 1163 - set time zone and other stuff in the principle object
if (Thread.CurrentPrincipal.Identity.IsAuthenticated && Username != "abcdefghijklmnopqrstuvwxyz" && Password != "abcdefghijklmnopqrstuvwxyz")
{
//case 2100 added in schema 91
decimal dtz = 9999;
if (AyaBizUtils.GlobalX.DBSchemaVersion > 90)
{
dtz = UserTimeZoneOffsetFetcher.UserTimeZoneOffset(User.CurrentThreadUserID);
}
if (dtz == 9999)
{
((BusinessPrincipal)Thread.CurrentPrincipal).OverrideTimeZone = false;
((BusinessPrincipal)Thread.CurrentPrincipal).TimeZoneOffset = 0;
}
else
{
((BusinessPrincipal)Thread.CurrentPrincipal).OverrideTimeZone = true;
((BusinessPrincipal)Thread.CurrentPrincipal).TimeZoneOffset = (double)dtz;
}
}
}
#endregion login
#region License entry license options properties
/// <summary>
///
/// </summary>
[Browsable(false)]
public static string stat
{
get
{
if (AyaBizUtils.Lite) return ""; //case 1172
long l = ScheduleableUserCountFetcher.GetItem();
if (User.IsAdmin && l > GlobalX.ScheduleableUsers)
{
return (
"LICENSE VIOLATION\r\n\r\n" +
"AyaNova has detected an attempt to circumvent AyaNova licensing.\r\n\r\n" +
"This database is licensed for " + GlobalX.ScheduleableUsers.ToString() + " scheduleable users\r\n" +
"Currently there are " + l.ToString() + " scheduleable users active.\r\n\r\n" +
"All AyaNova accounts other than Manager have been suspended until\r\n" +
"the extra scheduleable users that are not licensed are\r\n" +
"set inactive, removed or changed to non-scheduleable users\r\n" +
"to bring this database back into license compliance.\r\n\r\n" +
"Directly editing the AyaNova database can lead to lost or damaged data\r\n" +
"Please ensure no one tampers with the AyaNova database in future.\r\n\r\n" +
"** License violations are logged for the protection of the licensee and licensor **");
}
return "";
}
}
/// <summary>
/// True if the current AyaNova license is a trial version
/// </summary>
public static bool Trial
{
get
{//registered to "Unregistered trial" means true else false
return GlobalX.TrialKey;
}
}
/// <summary>
///
/// </summary>
[Browsable(false)]
public static int ScheduleableUsers
{
get
{
return GlobalX.ScheduleableUsers;
}
}
//case 2094 - now a plugin
///// <summary>
/////
///// </summary>
//[Browsable(false)]
//public static bool WBI
//{
// get
// {
// return GlobalX.FeatureWebInterface;
// }
//}
//case 2094 now a plugin
////Case 726
///// <summary>
/////
///// </summary>
//[Browsable(false)]
//public static bool MBI
//{
// get
// {
// return GlobalX.FeatureMBIInterface;
// }
//}
/// <summary>
/// Name of AyaNova licensee
/// </summary>
[Browsable(false)]
public static string REGTO
{
get
{
return GlobalX.RegisteredTo;
}
}
/// <summary>
/// downloaded trial expired
/// nothing to do with web requested trial or licensed trial which are under Lockdown and lockdowndate
/// </summary>
[Browsable(false)]
public static bool TrialExpired
{
get
{
return GlobalX.TrialExpired;
}
}
/// <summary>
///Requested trial expired (not the same as downloaded trial expire)
/// </summary>
[Browsable(false)]
public static bool LockedOut
{
get
{
return GlobalX.LockedOut;
}
}
/// <summary>
/// Downloaded trial will expire
/// </summary>
[Browsable(false)]
public static bool WillExpire
{
get
{
return GlobalX.WillExpire;
}
}
/// <summary>
/// Requested trial will expire
/// </summary>
[Browsable(false)]
public static bool WillLockout
{
get
{
return GlobalX.Lockout;
}
}
/// <summary>
/// Downloaded trial OR Subscription expiry date
/// </summary>
[Browsable(false)]
public static DateTime ExpiryDate
{
get
{
return GlobalX.ExpiryDate;
}
}
/// <summary>
/// Requested trial Lockout date
/// </summary>
[Browsable(false)]
public static DateTime LockoutDate
{
get
{
if (GlobalX.Lockout)
return GlobalX.LockoutDate;
else
return DateTime.MaxValue;
}
}
//case 999
/// <summary>
/// Used to prevent sequential entry of web requested trial license in winform license entry section
/// Used also to give menu option for trial user to swap between LITE and regular AyaNova when testing out
/// </summary>
[Browsable(false)]
public static bool RequestedTrial//web requested trial?
{
get
{
return GlobalX.RequestedTrial;
}
}
//License key entry from UI to db goes
//through here
/// <summary>
///
/// </summary>
/// <param name="sData"></param>
/// <returns></returns>
[Browsable(false)]
public static bool Insert(string sData)
{
//case 1172
bool bWasLite = Lite;
//case 997 count the active scheduleable users
int nActiveSchedUserCount = 0;
UserPickList upl = UserPickList.GetList(false);
foreach (UserPickList.UserPickListInfo i in upl)
{
if (i.Active && i.Type == UserTypes.Schedulable)
nActiveSchedUserCount++;
}
if (!User.IsAdmin && !Lite) return false;//case 1172
GlobalX.GlobalData = sData;
if (!GlobalX.IsSavable) return false;
try
{
GlobalX.Save();
//case 973
DBManager.ResetCacheInDataPortal.Reset();
}
catch
{
return false;
}
//License accepted and saved
//case 1172
_SchemaUpdating = true;
if (bWasLite == false && Lite)//going from full to lite?
{
User.CreateLiteUser();
DBManager.UnscheduleUsersToLite();
//deactivate all the other users
foreach (UserPickList.UserPickListInfo i in upl)
{
if (i.ID != User.LiteUserID && i.ID != User.AdministratorID)
{
User u = User.GetItem(i.ID);
u.Active = false;
if (u.DefaultWarehouseID == Guid.Empty)
u.DefaultWarehouseID = PartWarehouse.DefaultWarehouseID;
u.Save();
}
}
//case 1858
GlobalSettings.TaxPartPurchaseID = Guid.Empty;
GlobalSettings.Save();
}
else
{
//case 997
//Is new key for less users than there are currently active scheduleable users?
//if so, then unschedule all workorders and set
//all sched users to inactive
if (GlobalX.ScheduleableUsers < nActiveSchedUserCount)
{
//Set all scheduled users in workorder item scheduled user to null
DBManager.UnscheduleUsers();
//also set all scheduled users to inactive to avoid license key violation error
foreach (UserPickList.UserPickListInfo i in upl)
{
if (i.mType == UserTypes.Schedulable)
{
User u = User.GetItem(i.ID);
u.Active = false;
u.Save();
}
}
}
}
_SchemaUpdating = false;
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
[Browsable(false)]
public static string View()
{
return GlobalX.ViewGlobalData;
}
//case 2094 - plugins no longer have versions only expiry dates
/////case 1053
///// <summary>
///// return string version number or null if plugin requested is not licensed
///// </summary>
///// <param name="sPluginName"></param>
///// <returns></returns>
//[Browsable(false)]
//public static string PluginLicensedVersion(string sPluginName)
//{
// foreach (DataRow dr in GlobalX.Plugins.Rows)
// {
// if (dr["Plugin"].ToString() == sPluginName)
// {
// return dr["Version"].ToString();
// }
// }
// return "";
//}
//case 2094
/// <summary>
/// Get subscription expiry date for plugin
/// </summary>
/// <param name="sPluginName"></param>
/// <returns>DateTime.MinValue if not found else the subscription expiry date</returns>
[Browsable(false)]
public static DateTime PluginSubscriptionDate(string sPluginName)
{
if (GlobalX.SubscriptionLicense)
{
foreach (DataRow dr in GlobalX.Plugins.Rows)
{
if (dr["Plugin"].ToString() == sPluginName)
{
//case 3113
return (DateTime)dr["SubscriptionExpires"];
//return DateTime.Parse(dr["SubscriptionExpires"].ToString());
}
}
}
return DateTime.MinValue;
}
/// <summary>
/// Return plugin license status for assembly
/// </summary>
/// <param name="PluginName"></param>
/// <param name="BuildDate"></param>
/// <returns>"ok" if there is a subscription for the plugin and the plugin's build date is older than the subscription expiry date
/// or "NONE" if there is no license at all or "NOTALLOWED" if the plugins license subscription to date is older than the build of the plugin
/// </returns>
[Browsable(false)]
public static string PluginSubscriptionStatus(string PluginName, DateTime BuildDate)
{
DateTime dtExpires = PluginSubscriptionDate(PluginName);
if (dtExpires == DateTime.MinValue)
{
//Doesn't exist so no, can't use it at all
return "NONE";
}
//Timestamp.BuildAt > ExpiryDate
if (dtExpires < BuildDate)
{
//built after subscription expires
//not allowed to use--too new
return "NOTALLOWED";
}
return "OK";
}
//case 2094
/// <summary>
/// Check if plugin is built after subscription expired
/// </summary>
/// <param name="PluginName"></param>
/// <param name="BuildDate"></param>
/// <returns>true if built after license subscription expired or false</returns>
[Browsable(false)]
public static bool PluginTooNew(string PluginName, DateTime BuildDate)
{
return (PluginSubscriptionStatus(PluginName, BuildDate) == "NOTALLOWED");
}
//case 2094
/// <summary>
/// Check if plugin is allowed to run
/// Checks if there is a license for the plugin then
/// compares build date vs subscription date
/// </summary>
/// <param name="PluginName"></param>
/// <param name="BuildDate"></param>
/// <returns>true if allowed to start or false if not </returns>
[Browsable(false)]
public static bool PluginAllowed(string PluginName, DateTime BuildDate)
{
return (PluginSubscriptionStatus(PluginName, BuildDate) == "OK");
}
//case 2094
/// <summary>
/// Check if there is a license for named plugin
/// DOES NOT CHECK IF THE SUBSCRIPTION IS EXPIRED ONLY THAT IT EXISTS
/// </summary>
/// <param name="sPluginName"></param>
/// <returns></returns>
[Browsable(false)]
public static bool PluginSubscriptionExists(string sPluginName)
{
foreach (DataRow dr in GlobalX.Plugins.Rows)
{
if (dr["Plugin"].ToString() == sPluginName)
{
return true;
}
}
return false;
}
/// <summary>
/// Subscription license has expired
/// </summary>
public static bool SubscriptionExpired
{
get
{
return GlobalX.SubscriptionExpired;
}
}
/// <summary>
/// Subscription license will expire soon
/// </summary>
public static bool SubscriptionExpirationImminent
{
get
{
TimeSpan ts2 = GlobalX.ExpiryDate.Subtract(System.DateTime.Now);
if (ts2.TotalDays > 0 && ts2.TotalDays < 10)
return true;
return false;
}
}
//case 1172
/// <summary>
/// True if AyaNova is running in Lite mode
/// </summary>
public static bool Lite
{
get
{
return GlobalX.Lite;
}
}
/// <summary>
/// AyaNova license id
/// </summary>
public static string LicId
{
//case 3712 - added for QBOI with oAuth2 usage
get
{
return GlobalX.DigestValue;
}
}
#endregion
#region Rights
/// <summary>
/// Check current thread user's rights to object specified by RootObjectType string
/// </summary>
/// <example>
/// Example usage - Checking if the currently logged in user has sufficient rights to access a <see cref="Client"/> object:
/// <code>
/// Client c=null;
/// if(AyaBizUtils.Right("Object.Client")&lt;(int)SecurityLevelTypes.ReadOnly)
/// c=Client.GetItem(myID);
/// else
/// MessageBox.Show("You don't have sufficient rights to open a client - Bazinga!"); //;)
///</code>
/// </example>
/// <param name="sObject">string representation of <see cref="RootObjectTypes"/> object</param>
/// <returns>int value corresponding to <see cref="SecurityLevelTypes"/> enum</returns>
public static int Right(string sObject)
{
//case 2094
if (LockDown) return 2;
if (_SchemaUpdating) return 4;
//case 1584
//case 1387
if (sObject == "Object.Workorder")
{
sObject = "Object.WorkorderService";
#if(DEBUG)
throw new System.Exception("CASE 1387 ERROR: AyaBizUtils->Right - RootObject rights being checked is Workorder!");
#endif
}
//don't allow trial to edit users
//case 3646 removed
//if (Trial && sObject == "Object.User") return 2;
if (GlobalX.TrialExpired || GlobalX.LockedOut)
return 2;
if (sObject.EndsWith("Template")) sObject = sObject.Replace("Template", "");
//case 1592
if (sObject == "Object.WorkorderItemPartRequest") sObject = "Object.WorkorderItemPart";
//case 1172
if (Lite)
{
switch (sObject)
{
case "Object.WorkorderPreventiveMaintenance":
case "Object.WorkorderQuote":
case "Object.ClientGroup":
case "Object.DispatchZone":
// case "Object.PartAssembly":
case "Object.PartWarehouse":
case "Object.Unit":
case "Object.UnitModel":
case "Object.UnitModelCategory":
//case "Object.UnitOfMeasure":
case "Object.UnitServiceType":
case "Object.UserCertification":
case "Object.UserCertificationAssigned":
case "Object.UserSkill":
case "Object.UserSkillAssigned":
//case "Object.WorkorderItemType":
case "Object.WikiPage":
case "Object.AssignedDocument":
case "Object.AssignedDoc":
case "Object.LoanItem":
case "Object.Region":
case "Object.SecurityGroup":
case "Object.Notification":
case "Object.AyaFile":
case "Object.HeadOffice":
case "Object.Contract":
case "Object.ClientServiceRequest":
case "Object.Project":
case "Object.Memo":
return (int)SecurityLevelTypes.NoAccess;
default:
return (int)SecurityLevelTypes.ReadWriteDelete;//Otherwise full access since no security in lite version
}
}
return ((BusinessPrincipal)Thread.CurrentPrincipal).Right(sObject);
}
/// <summary>
/// Check current thread user's rights to Root object type specified
/// </summary>
/// <example>
/// Example usage - Checking if the currently logged in user has sufficient rights to access a <see cref="Client"/> object:
/// <code>
/// Client c=null;
/// if(AyaBizUtils.Right(RootObjectTypes.Client)&lt;(int)SecurityLevelTypes.ReadOnly)
/// c=Client.GetItem(myID);
/// else
/// MessageBox.Show("You don't have sufficient rights to open a client - Bazinga!"); //;)
///</code>
/// </example>
/// <param name="RootObject"><see cref="RootObjectTypes"/> object type</param>
/// <returns>int value corresponding to <see cref="SecurityLevelTypes"/> enum</returns>
[Browsable(false)]
public static int Right(RootObjectTypes RootObject)
{
//case 2094
if (LockDown) return 2;
if (_SchemaUpdating) return 4;
//case 1584
// System.Diagnostics.Debug.Assert(RootObject != RootObjectTypes.Workorder, "AyaBizUtils->Right something is checking the rights to the Workorder object deprecated in case 1387");
if (RootObject == RootObjectTypes.Workorder)
{
RootObject = RootObjectTypes.WorkorderService;
#if(DEBUG)
throw new System.Exception("CASE 1387 ERROR: AyaBizUtils->Right - RootObject rights being checked is Workorder!");
#endif
}
//case 3646 removed
//don't allow trial to edit users
//if (Trial && RootObject == RootObjectTypes.User) return 2;
if (GlobalX.TrialExpired || GlobalX.LockedOut)
return 2;
if (RootObject == RootObjectTypes.WorkorderQuoteTemplate) RootObject = RootObjectTypes.WorkorderQuote;
if (RootObject == RootObjectTypes.WorkorderServiceTemplate) RootObject = RootObjectTypes.WorkorderService;
if (RootObject == RootObjectTypes.WorkorderPreventiveMaintenanceTemplate) RootObject = RootObjectTypes.WorkorderPreventiveMaintenance;
//case 1592
if (RootObject == RootObjectTypes.WorkorderItemPartRequest) RootObject = RootObjectTypes.WorkorderItemPart;
//case 1172
if (Lite)
{
switch (RootObject)
{
case RootObjectTypes.WorkorderPreventiveMaintenance:
case RootObjectTypes.WorkorderQuote:
case RootObjectTypes.ClientGroup:
case RootObjectTypes.DispatchZone:
//case RootObjectTypes.PartAssembly:
case RootObjectTypes.PartWarehouse:
case RootObjectTypes.Unit:
case RootObjectTypes.UnitModel:
case RootObjectTypes.UnitModelCategory:
//case RootObjectTypes.UnitOfMeasure:
case RootObjectTypes.UnitServiceType:
case RootObjectTypes.UserCertification:
case RootObjectTypes.UserCertificationAssigned:
case RootObjectTypes.UserSkill:
case RootObjectTypes.UserSkillAssigned:
//case RootObjectTypes.WorkorderItemType:
case RootObjectTypes.WikiPage:
case RootObjectTypes.AssignedDocument:
case RootObjectTypes.LoanItem:
case RootObjectTypes.Region:
case RootObjectTypes.SecurityGroup:
case RootObjectTypes.Notification:
case RootObjectTypes.AyaFile:
case RootObjectTypes.HeadOffice:
case RootObjectTypes.Contract:
case RootObjectTypes.ClientServiceRequest:
case RootObjectTypes.Project:
case RootObjectTypes.Memo:
return (int)SecurityLevelTypes.NoAccess;
default:
return (int)SecurityLevelTypes.ReadWriteDelete;//Otherwise full access since no security in lite version
}
}
return ((BusinessPrincipal)Thread.CurrentPrincipal).Right("Object." + RootObject.ToString());
}
/// <summary>
/// Check if currently logged in user has at least the right specified to the object specified
/// </summary>
/// <param name="ObjectType"></param>
/// <param name="SecureLevel"></param>
/// <returns></returns>
public static bool HasRight(RootObjectTypes ObjectType, SecurityLevelTypes SecureLevel)
{
return ((int)Right(ObjectType) > (int)SecureLevel);
}
/// <summary>
/// Check current logged in user's right to
/// read the object type specified
/// </summary>
/// <param name="ObjectType">RootObjectType</param>
/// <returns>true or false</returns>
public static bool CanRead(RootObjectTypes ObjectType)
{
return ((int)Right(ObjectType) > (int)SecurityLevelTypes.NoAccess);
}
/// <summary>
/// Check current logged in user's right to
/// read and write the object type specified
/// </summary>
/// <param name="ObjectType">RootObjectType</param>
/// <returns>true or false</returns>
public static bool CanWrite(RootObjectTypes ObjectType)
{
return ((int)Right(ObjectType) > (int)SecurityLevelTypes.ReadOnly);
}
/// <summary>
/// Check current logged in user's right to
/// read, write and delete the object type specified
/// </summary>
/// <param name="ObjectType">RootObjectType</param>
/// <returns>true or false</returns>
public static bool CanWriteAndDelete(RootObjectTypes ObjectType)
{
return ((int)Right(ObjectType) > (int)SecurityLevelTypes.ReadWrite);
}
private static bool mIsTemporaryGenerator = false;
/// <summary>
///
/// </summary>
[Browsable(false)]
public static bool TG
{
set
{
mIsTemporaryGenerator = value;
}
}
[Browsable(false)]
internal static bool IsGenerator
{
get
{
return mIsTemporaryGenerator || ((BusinessPrincipal)Thread.CurrentPrincipal).IsGenerator;
}
}
#endregion
#region Word breaker
//static Hashtable StopWords;
#pragma warning disable 1591
static AyaBizUtils()
{
}
#region Breaker
public enum TokenTypes
{ Nothing, Separator, CJK, Latin };
/// <summary>
/// Take an array of strings and
/// return a single xml string
/// containing unique only, lowercase
/// keywords suitable for passing to a
/// stored procedure or other function that can
/// handle very plain xml
///
/// Use GlobalSettings.CJKIndex=true to handle Chinese, Japanese, Korean etc
/// (languages with no easily identifiable word boundaries as in english)
/// </summary>
///
/// <param name="AsXML">return results as XML or as a string of comma delimited words</param>
/// <param name="text">An array of 0 to * strings of text</param>
/// <returns></returns>
internal static string Break(bool AsXML, params string[] text)
{
return BreakCore(false, AsXML, text);
}
/// <summary>
/// Used to Process users search phrase and preserve wild
/// cards entered
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
internal static string BreakSearchPhrase(params string[] text)
{
return BreakCore(true, false, text);
}
/// <summary>
/// Stop words list reset upon login or editing of localized text
/// used for eliminating noise words from search dictionary
/// </summary>
public static System.Collections.Generic.List<string> StopList = null;
internal static string BreakCore(bool KeepWildCards, bool AsXML, params string[] text)
{
////case 1039 //log.Debug("Break");
#region stopwords
if (StopList == null)
{
StopList = new List<string>();
for (int stopkeys = 1; stopkeys < 8; stopkeys++)
{
MatchCollection mc = rxAllWords.Matches(LocalizedTextTable.GetLocalizedTextDirect("StopWords" + stopkeys.ToString()));
foreach (Match m in mc)
{
if (!string.IsNullOrEmpty(m.Value) && m.Value != "?" && !StopList.Contains(m.Value))
StopList.Add(m.Value);
}
}
}
#endregion
bool CJK = GlobalSettings.CJKIndex;
int MAXWORDLENGTH = 255;
StringBuilder sbResults = new StringBuilder();
//Hashtable to temporarily hold parsed words
//used to easily ensure unique words only
Hashtable ht = new Hashtable();
//Stuff required for creating xml fragment on the fly in memory (string)
StringBuilder sb = new StringBuilder();
StringBuilder sbWord = new StringBuilder();
System.IO.StringWriter sr = new System.IO.StringWriter(sb);
System.Xml.XmlTextWriter w = new System.Xml.XmlTextWriter(sr);
w.Formatting = System.Xml.Formatting.Indented;
w.WriteStartElement("Items");
//Loop through each of the passed in strings
foreach (string s in text)
{
if (s == null || s == "") continue;
//get all the characters in a unicode compliant manner...
TextElementEnumerator t = StringInfo.GetTextElementEnumerator(s);
//start at the top
t.Reset();
TokenTypes LastToken = TokenTypes.Nothing;
//Used by CJK
bool BasicLatinBlock = true;
//Process each "character" (text element,glyph whatever) in the
//current string
while (t.MoveNext())
{
//get it as a character
char c = t.GetTextElement()[0];
if (!CJK)
{
#region regular tokenizer
//Is it a token we want to include?
//Or a wildcard character
if (char.IsLetterOrDigit(c) || (KeepWildCards && c == '%'))
{
#region Include token
//All latin text is converted to lower case
c = char.ToLower(c);
//Do we already have a word?
if (sbWord.Length > 0)
{
//Maybe we need to flush this word into the word list
//if we're over the word length limit
if (sbWord.Length >= MAXWORDLENGTH)
{
//flush away...
if (!ht.ContainsKey(sbWord.ToString()))
{
ht[sbWord.ToString()] = 1;
//sbTest.Append(sbWord.ToString()+"\r\n");
}
sbWord.Length = 0;
sbWord.Append(c);
LastToken = TokenTypes.Latin;
continue;
}
}
//append character and go on to next one
sbWord.Append(c);
LastToken = TokenTypes.Latin;
continue;
#endregion
}
else
{
#region Word Boundary token
LastToken = TokenTypes.Separator;
if (sbWord.Length > 0)
{
//flush away...
if (!ht.ContainsKey(sbWord.ToString()))
{
ht[sbWord.ToString()] = 1;
//sbTest.Append(sbWord.ToString()+"\r\n");
}
sbWord.Length = 0;
continue;
}
#endregion
}
#endregion
}
else
{
#region CJK Tokenizer
//Is it a basic latin charater? (ascii basically)
//see: http://www.unicode.org/charts/index.html
//and here for a funky online viewer:
//http://www.fileformat.info/info/unicode/block/index.htm
//we need to know this so that regular english text
//within cjk text gets properly indexed as whole words
BasicLatinBlock = false;
if ((int)c < 256) BasicLatinBlock = true;
if (BasicLatinBlock)
{
//Is it a token we want to include?
if (char.IsLetterOrDigit(c) || (KeepWildCards && c == '%'))
{
#region Latin Include token
//All latin text is converted to lower case
c = char.ToLower(c);
//Do we already have a word?
if (sbWord.Length > 0)
{
//Maybe we need to flush this word into the word list
//if we're over the word length limit or we are going from
//CJK to latin
if (LastToken == TokenTypes.CJK || sbWord.Length >= MAXWORDLENGTH)
{
//flush away...
if (!ht.ContainsKey(sbWord.ToString()))
{
ht[sbWord.ToString()] = 1;
//sbTest.Append(sbWord.ToString()+"\r\n");
}
sbWord.Length = 0;
sbWord.Append(c);
LastToken = TokenTypes.Latin;
continue;
}
}
//append character and go on to next one
sbWord.Append(c);
LastToken = TokenTypes.Latin;
continue;
#endregion
}
else
{
#region Latin Word Boundary token
LastToken = TokenTypes.Separator;
if (sbWord.Length > 0)
{
//flush away...
if (!ht.ContainsKey(sbWord.ToString()))
{
ht[sbWord.ToString()] = 1;
//sbTest.Append(sbWord.ToString()+"\r\n");
}
sbWord.Length = 0;
continue;
}
#endregion
}
}
else//CJK character
{
if (char.IsLetter(c) || (KeepWildCards && c == '%'))
{
#region CJK Include token
//Do we already have a word?
if (sbWord.Length > 0)
{
//Maybe we need to flush this word into the word list
//if we're over the word length limit or we are going from
//latin TO CJK
if (LastToken == TokenTypes.Latin || sbWord.Length >= MAXWORDLENGTH)
{
//flush away...
if (!ht.ContainsKey(sbWord.ToString()))
{
ht[sbWord.ToString()] = 1;
//sbTest.Append(sbWord.ToString()+"\r\n");
}
sbWord.Length = 0;
sbWord.Append(c);
LastToken = TokenTypes.CJK;
continue;
}
if (LastToken == TokenTypes.CJK)
{
//we're here because there is more than zero characters already stored
//and the last was CJK so we need append current character
//and flush the resultant 2 character n-gram
sbWord.Append(c);
System.Diagnostics.Debug.Assert(sbWord.Length == 2);
if (!ht.ContainsKey(sbWord.ToString()))
{
ht[sbWord.ToString()] = 1;
//sbTest.Append(sbWord.ToString()+"\r\n");
}
sbWord.Length = 0;
sbWord.Append(c);
LastToken = TokenTypes.CJK;
continue;
}
}
//append character and go on to next one
sbWord.Append(c);
LastToken = TokenTypes.CJK;
continue;
#endregion
}
else
{
#region CJK Word Boundary token
LastToken = TokenTypes.Separator;
if (sbWord.Length > 0)
{
//flush away...
if (!ht.ContainsKey(sbWord.ToString()))
{
ht[sbWord.ToString()] = 1;
//sbTest.Append(sbWord.ToString()+"\r\n");
}
sbWord.Length = 0;
continue;
}
#endregion
}
}
#endregion
}
}
//Flush out the last word
if (sbWord.Length > 0)
{
//flush away...
if (!ht.ContainsKey(sbWord.ToString()))
{
ht[sbWord.ToString()] = 1;
////sbTest.Append(sbWord.ToString()+"\r\n");
}
sbWord.Length = 0;
}
}
//bail early if there is nothing indexed
if (ht.Count == 0) return "";
if (AsXML)
{
//Make a return xml fragment
//from the word list
foreach (DictionaryEntry d in ht)
{
//Add only non stopwords
if (!StopList.Contains(d.Key.ToString()))
{
w.WriteStartElement("i");
w.WriteAttributeString("w", d.Key.ToString());
w.WriteEndElement();
}
}
w.WriteEndElement();
sr.Close();
return sr.ToString();
}
else
{
//Make a return string array
//from the word list
foreach (DictionaryEntry d in ht)
{
//Add only non stopwords
if (!StopList.Contains(d.Key.ToString()))
{
sbResults.Append(d.Key.ToString());
sbResults.Append(",");
}
}
//sometimes all the results are stop words so you end up
//here with nothing in sbResults. Removed some code that was
//causing a crash here
return sbResults.ToString().TrimEnd(',');
}
//return sbTest.ToString();
}
#endregion
#pragma warning restore 1591
#endregion
#region Searchable Biz object GetSearchResult
/// <summary>
/// Instantiates searchable business objects based on type and id (class factory)
/// and Processes and returns search result for that object
/// </summary>
/// <param name="RootObjectType"></param>
/// <param name="RootObjectID"></param>
/// <param name="searchTerms"></param>
/// <returns></returns>
public static SearchResult GetSearchResultFor(RootObjectTypes RootObjectType, Guid RootObjectID, string[] searchTerms)
{
//if(log.IsDebugEnabled)
// //case 1039 //log.Debug("GetSearchResultFor(Type=" + RootObjectType.ToString() + ", ID=" + RootObjectID.ToString());
switch (RootObjectType)
{
case RootObjectTypes.Client:
return Client.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.AssignedDocument:
return AssignedDoc.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.ClientGroup:
return ClientGroup.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.ClientNote:
return ClientNote.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.ClientServiceRequest:
return ClientServiceRequest.GetSearchResult(RootObjectID, searchTerms);
//Removed finally as part of case 58
case RootObjectTypes.Contact:
return new SearchResult();//JUST RETURN EMPTY RESULT SO NO ERROR DURING DEVELOPMENT OF CASE 1975
// return xContact.GetSearchResult(RootObjectID, searchTerms);
//case RootObjectTypes.ContactPhone:
// return xContactPhone.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.Contract:
return Contract.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.DispatchZone:
return DispatchZone.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.HeadOffice:
return HeadOffice.GetSearchResult(RootObjectID, searchTerms);
//Memo will only return a result if the sender is current user
//or the receiver is current user
//UNLESS the current user is the built in admin account
case RootObjectTypes.Memo:
return Memo.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.Part:
return Part.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.PartAssembly:
return PartAssembly.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.PartWarehouse:
return PartWarehouse.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.Project:
return Project.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.PurchaseOrder:
return PurchaseOrder.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.Rate:
return Rate.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.ScheduleableUserGroup:
return ScheduleableUserGroup.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.ScheduleMarker:
return ScheduleMarker.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.ServiceBank:
return ServiceBank.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.Task:
return Task.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.TaskGroup:
return TaskGroup.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.Unit:
return Unit.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.LoanItem:
return LoanItem.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.UnitMeterReading:
return UnitMeterReading.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.UnitModel:
return UnitModel.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.UnitModelCategory:
return UnitModelCategory.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.UnitServiceType:
return UnitServiceType.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.User:
return User.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.UserCertification:
return UserCertification.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.UserSkill:
return UserSkill.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.Vendor:
return Vendor.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.Workorder:
return Workorder.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderService:
return WorkorderService.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderQuote:
return WorkorderQuote.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderPreventiveMaintenance:
return WorkorderPreventiveMaintenance.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderCategory:
return WorkorderCategory.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderItem:
return WorkorderItem.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderItemLabor:
return WorkorderItemLabor.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderItemMiscExpense:
return WorkorderItemMiscExpense.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderItemOutsideService:
return WorkorderItemOutsideService.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderItemPart:
return WorkorderItemPart.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderItemTravel:
return WorkorderItemTravel.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderItemLoan:
return WorkorderItemLoan.GetSearchResult(RootObjectID, searchTerms);
case RootObjectTypes.WorkorderItemType:
return WorkorderItemType.GetSearchResult(RootObjectID, searchTerms);
//Added: 24-June-2006 was missing
case RootObjectTypes.PartInventoryAdjustment:
return PartInventoryAdjustment.GetSearchResult(RootObjectID, searchTerms);
//case 73
case RootObjectTypes.WikiPage:
return WikiPage.GetSearchResult(RootObjectID, searchTerms);
default:
//if all else fails, return an empty search result struct
{
//KEEP THIS FOR FUTURE DIAGNOSTICS
#if(DEBUG)
throw new System.ArgumentException("AyaBizUtils->GetSearchResultFor: " + RootObjectType.ToString() + " IS NOT IMPLEMENTED");
#else
//case 1116
return new SearchResult();
#endif
}
}
}
#endregion
#region Grid Filtering and sorting
#pragma warning disable 1591
/// <summary>
///
/// </summary>
/// <param name="XmlGridCriteria"></param>
/// <param name="AddOrderByCommand"></param>
/// <returns></returns>
public static string GetGridSortOrderColumns(string XmlGridCriteria, bool AddOrderByCommand)
{
//if(log.IsDebugEnabled)
// //case 1039 //log.Debug("GetGridSortOrderColumns(XmlGridCriteria=" + XmlGridCriteria);
//Added 05-May-2006: An empty criteria was triggering an exception
//changed to just short circuit if empty
if (XmlGridCriteria == "") return "";
//change: 07-June-2006 Moved dupe checking here
//because we need to allow dupes for the UI sort order code
Hashtable htFields = new Hashtable();
//Pre-add the "grid" sql column name
//because it indicates a column that is not sorted by the sql server (i.e. calculated)
htFields.Add("grid", 0);
try
{
StringReader sr = new StringReader(EscapeXml(XmlGridCriteria));//case 1724
DataSet ds = new DataSet();
ds.ReadXml(sr);
//Handle an empty dataset
if (!ds.Tables.Contains("COLUMNITEM"))
return "";
StringBuilder sb = new StringBuilder();
if (AddOrderByCommand)
sb.Append("ORDER BY ");
string sCurrentColumnName = "";
//Iterate through all tabs
bool bFirst = true;
//Added: 22-May-2006 moved limit of 4 columns to order by to here
//from the UI Util class GetGridSortAndFilterCriteria method
int nSortColumnsAddedToCriteria = 0;
foreach (DataRow TabRow in ds.Tables["COLUMNITEM"].Rows)
{
#if (DEBUG)
//If running in debug mode then order by all columns
//which reveals any mis spelled column names or missing
//column name attribute that might go missed
if (nSortColumnsAddedToCriteria > 4) break;//catch those nasty sql errors
#else
//In a release build only order by first 4 columns for performance
//anything more is pretty much redundant 99.9% of the time
if(nSortColumnsAddedToCriteria>4) break;
#endif
sCurrentColumnName = TabRow["CM"].ToString();
//duplicate elimination (moved here from Ui Util code
//because "dupes" are needed there
if (htFields.Contains(sCurrentColumnName))
continue;
htFields.Add(sCurrentColumnName, 0);
//ntext, image etc can't be ordered by
//that means not including those types here
if (sCurrentColumnName.IndexOf(".Custom") == -1)
{
//special Processing for first order by item (sort order)
if (bFirst)
{
//case 3604
//added check for column SORT
if (TabRow.Table.Columns.Contains("SORT") && TabRow["SORT"].ToString() == "DESC")
sb.Append(/*""+*/sCurrentColumnName + " DESC, ");
else
sb.Append(/*""+*/sCurrentColumnName + ", ");
bFirst = false;
}
else
sb.Append(/*""+*/sCurrentColumnName + ", ");
nSortColumnsAddedToCriteria++;
}
}
//take off the comma space at the end
sb.Remove(sb.Length - 2, 2);
//Changed 24-March-2006 for norwegian aA handling
return sb.ToString().ToUpper(System.Globalization.CultureInfo.InvariantCulture);
}
catch
{
//case 3603
#if (DEBUG)
throw;
#else
return "";
#endif
}
}
/// <summary>
/// Take an XML fragment containing the grid criteria
/// extract out the column order, build an ORDERBY
/// clause and return it as a string
/// </summary>
/// <param name="XmlGridCriteria"></param>
/// <returns></returns>
public static string GetGridSortOrderColumns(string XmlGridCriteria)
{
return GetGridSortOrderColumns(XmlGridCriteria, true);
}
/// <summary>
/// Takes an XML fragment containing the grid criteria
/// extracts out the filter criteria
/// builds a WHERE clause
/// and returns it as a string
/// </summary>
/// <param name="XmlGridCriteria"></param>
/// <param name="bAddWhere"></param>
/// <returns></returns>
public static string GetGridColumnCriteria(string XmlGridCriteria, bool bAddWhere)
{
//if(log.IsDebugEnabled)
// //case 1039 //log.Debug("GetGridColumnCriteria(XmlGridCriteria=" + XmlGridCriteria);
//Added 05-May-2006: An empty criteria was triggering an exception
//changed to just short circuit if empty
if (XmlGridCriteria == "") return "";
try
{
StringReader sr = new StringReader(EscapeXml(XmlGridCriteria));//case 1724
DataSet ds = new DataSet();
ds.ReadXml(sr);
//Handle an empty dataset
if (!ds.Tables.Contains("WHEREITEM"))
return "";
StringBuilder sb = new StringBuilder();
if (bAddWhere)
{
sb.Append(" WHERE ");
}
else//already has built in where keyword
{
sb.Append(" AND ");
}
bool bFirstGroup = true;
//WHEREITEMGROUP_WHEREITEM
foreach (DataRow GroupRow in ds.Tables["WHEREITEMGROUP"].Rows)
{
//Get the OR or AND
string sLogicalOperator = GroupRow["GROUPLOGICALOPERATOR"].ToString();
//It's possible that there is a group but no children in the case
//of certain types of criteria (regex etc) so check first
if (GroupRow.GetChildRows("WHEREITEMGROUP_WHEREITEM").GetLength(0) < 1)
continue;
//Ok, we have child rows, so start a new chunk of SQL
if (!bFirstGroup)
sb.Append(" AND ");
sb.Append("(");
bool bFirst = true;
DataRow[] groupChildren = GroupRow.GetChildRows("WHEREITEMGROUP_WHEREITEM");
bool bCompoundGroup = (groupChildren.GetLength(0) > 1);
foreach (DataRow ChildRow in groupChildren)
{
if (!bFirst)
sb.Append(" " + sLogicalOperator + " ");
//changed: 05-June-2006 to uppercase the column name
sb.Append(GridToSqlCriteria(
ChildRow["CM"].ToString().ToUpper(System.Globalization.CultureInfo.InvariantCulture),
ChildRow["TYPE"].ToString(),
ChildRow["COMPAREOPERATOR"].ToString(),
ChildRow["COMPAREVALUE"].ToString(),
bCompoundGroup));
bFirst = false;
}
sb.Append(") ");
bFirstGroup = false;
}
// //Iterate through all tabs
// foreach(DataRow TabRow in ds.Tables["WHEREITEM"].Rows)
// {
// sb.Append("(");
// sb.Append(GridToSqlCriteria(TabRow["COLUMN"].ToString(),TabRow["DATATYPE"].ToString(),
// TabRow["COMPAREOPERATOR"].ToString(),TabRow["COMPAREVALUE"].ToString()));
// sb.Append(") AND ");
//
// }
//
// //take off the comma space at the end
// sb.Remove(sb.Length-5,5);
//if(log.IsDebugEnabled)
// //case 1039 //log.Debug("GetGridColumnCriteria: returning[" + sb.ToString() + "]");
//Changed 24-March-2006 for norwegian aA handling
//Changed again 05-June-2006 can't shift whole thing to upper case
//as the criteria value of string values wouldn't match so
//added code above to just uppercase the table and column name
return sb.ToString();//.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
}
catch
{
//case 3603
#if (DEBUG)
throw;
#else
return "";
#endif
}
}
/// <summary>
/// Used internally by AyaNova UI to translate Infragistics grid filter settings to AyaNova friendly SQL critiera
/// </summary>
private static string GridToSqlCriteria(string sColumn, string sDataType, string sOperator, string sValue, bool IsCompound)
{
//if(log.IsDebugEnabled)
////case 1039 //log.Debug("GridToSqlCriteria(Column=" + sColumn +", DataType=" + sDataType + ", Operator=" + sOperator + ", Value=" + sValue+")");
StringBuilder sb = new StringBuilder();
//Column name
//sb.Append(" ");
sb.Append(sColumn);
sb.Append(" ");
//Added: 13-July-2006 prior fix on the 6th either broke due to other changes or
//was not enough in the first place, oddly it was working then, but this is also needed
//now to make it work:
//Handle bools with null values
//this comes about from a user selecting blanks or nonblanks to filter a bool column
if (sValue == "" && sDataType == "System.Boolean")
{
sValue = "False";
}
//handle null values separately
if (sValue == "")
{
//strings in grids are rarely null, almost always just an empty string
//so filter on that instead
switch (sDataType)
{
case "System.String":
{
if (sOperator == "Equals")
{
//Changed: 19-July-2006 was missing null values, "almost always' above not good enough!
sb.Append("Is Null");
sb.Append(" OR ");
sb.Append(sColumn);
sb.Append(" = ''");
}
else
sb.Append(" <> ''");
}
break;
default:
{
if (sOperator == "Equals")
sb.Append("Is Null");
else
sb.Append("Is Not Null");
}
break;
}
}
else
{//non null value
//Changed 21-March-2006:
//But wait! Both mssql and firebird won't include a null result
//on the filter field so in some cases we need to include them
//i.e. if a value is supposed to be not equal to a specific non-null value
//then null is a valid value to return but won't be normally
//so....
//Special addition to handle nulls
if (!IsCompound)
{
switch (sOperator)
{
case "Equals":
//no change on equals for nulls
break;
case "GreaterThan":
//no change on greater than for nulls
//(nulls are going to be assumed to be always at the
//less than end of the scale)
break;
case "GreaterThanOrEqualTo":
//no change on greater than for nulls
//(nulls are going to be assumed to be always at the
//less than end of the scale)
break;
case "LessThan":
sb.Append("Is Null OR ");
sb.Append(sColumn);
sb.Append(" ");
break;
case "LessThanOrEqualTo":
sb.Append("Is Null OR ");
sb.Append(sColumn);
sb.Append(" ");
break;
case "Like":
//No change on like
break;
case "NotEquals":
//This is the big one:
sb.Append("Is Null OR ");
sb.Append(sColumn);
sb.Append(" ");
break;
}
}
#region Build for specific type
switch (sDataType)
{
case "System.String":
//escape any pre-existing apostrophes
//i.e. "O'Flaherty's pub" would cause fits
//if this wasn't done
//MS-sql and firebird use double apostrophes so
//any future db added should consider this
sValue = sValue.Replace("'", "''");
//case 1951 - unescape ampersands
sValue = sValue.Replace("&amp;", "&");
//case 3581
string insertNationalTypeQueryCharacter = string.Empty;
if (DBUtil.DB.DBType == DataBaseType.MSSQL)
{
insertNationalTypeQueryCharacter = "N";
}
switch (sOperator)
{
case "Equals":
sb.Append("=" + insertNationalTypeQueryCharacter + "'");
sb.Append(sValue);
sb.Append("'");
break;
case "GreaterThan":
sb.Append(">" + insertNationalTypeQueryCharacter + "'");
sb.Append(sValue);
sb.Append("'");
break;
case "GreaterThanOrEqualTo":
sb.Append(">=" + insertNationalTypeQueryCharacter + "'");
sb.Append(sValue);
sb.Append("'");
break;
case "LessThan":
sb.Append("<" + insertNationalTypeQueryCharacter + "'");
sb.Append(sValue);
sb.Append("'");
break;
case "LessThanOrEqualTo":
sb.Append("<=" + insertNationalTypeQueryCharacter + "'");
sb.Append(sValue);
sb.Append("'");
break;
case "Like":
sb.Append("Like " + insertNationalTypeQueryCharacter + "'");
sb.Append(sValue);
sb.Append("%'");
break;
case "NotEquals":
sb.Append("<>" + insertNationalTypeQueryCharacter + "'");
sb.Append(sValue);
sb.Append("'");
break;
//Following 7 operators added 14-June-2006
case "DoesNotContain":
sb.Append("Not Like " + insertNationalTypeQueryCharacter + "'%");
sb.Append(sValue);
sb.Append("%'");
break;
case "Contains":
sb.Append("Like " + insertNationalTypeQueryCharacter + "'%");
sb.Append(sValue);
sb.Append("%'");
break;
case "StartsWith":
sb.Append("Like " + insertNationalTypeQueryCharacter + "'");
sb.Append(sValue);
sb.Append("%'");
break;
case "EndsWith":
sb.Append("Like " + insertNationalTypeQueryCharacter + "'%");
sb.Append(sValue);
sb.Append("'");
break;
case "DoesNotStartWith":
sb.Append("Not Like " + insertNationalTypeQueryCharacter + "'");
sb.Append(sValue);
sb.Append("%'");
break;
case "DoesNotEndWith":
sb.Append("Not Like " + insertNationalTypeQueryCharacter + "'%");
sb.Append(sValue);
sb.Append("'");
break;
case "NotLike":
sb.Append("Not Like " + insertNationalTypeQueryCharacter + "'");
sb.Append(sValue);
sb.Append("%'");
break;
default:
throw new System.ArgumentOutOfRangeException("OPERATOR_TYPE", sOperator, "GridToSqlCriteria unhandled operator type [" + sOperator + "] IN STRING");
}
break;
case "System.Boolean":
{
switch (sOperator)
{
case "Equals":
sb.Append("= ");
if (sValue == "True")
sb.Append("1");
else
sb.Append("0");
break;
case "NotEquals":
sb.Append("<> ");
if (sValue == "True")
sb.Append("1");
else
sb.Append("0");
break;
default:
throw new System.ArgumentOutOfRangeException("OPERATOR_TYPE", sOperator, "GridToSqlCriteria unhandled operator type [" + sOperator + "] in BOOL");
}
}
break;
case "System.Guid":
{
switch (sOperator)
{
case "Equals":
sb.Append("= ");
sb.Append("'");
sb.Append(sValue);
sb.Append("'");
break;
case "NotEquals":
sb.Append("<> ");
sb.Append("'");
sb.Append(sValue);
sb.Append("'");
break;
default:
throw new System.ArgumentOutOfRangeException("OPERATOR_TYPE", sOperator, "GridToSqlCriteria unhandled operator type [" + sOperator + "] in BOOL");
}
}
break;
case "System.DateTime":
case "System.Object":
{
//ref http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdatetimeclasstostringtopic.asp
//s format = sql server universal date time pattern, e.g. 2004-09-28 14:14:45
if (sValue.StartsWith("["))
{
#region Build criteria for date RANGE specified
//Used as the basis point
System.DateTime dtAfter;
System.DateTime dtBefore;
switch (sValue)
{
//Case 402
case "[YESTERDAY]":
//Between Day before yesterday at midnight and yesterday at midnight
dtAfter = System.DateTime.Today.AddDays(-1);
dtAfter = dtAfter.AddSeconds(-1);
dtBefore = System.DateTime.Today;//.AddDays(-1);
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[TODAY]":
//Between yesterday at midnight and tommorow at midnight
dtAfter = System.DateTime.Today.AddSeconds(-1);
dtBefore = System.DateTime.Today.AddDays(1);
//dtBefore=dtBefore.AddSeconds(1);
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
//sb.Append(" ");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[TOMORROW]":
//Between Tonight at midnight and day after tommorow at midnight
dtAfter = System.DateTime.Today.AddDays(1);
dtAfter = dtAfter.AddSeconds(-1);
dtBefore = System.DateTime.Today.AddDays(2);
//dtBefore=dtBefore.AddSeconds(1);
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
//sb.Append(" ");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
//Case 402
case "[LAST WEEK]":
//Between two Sundays ago at midnight and last sunday at midnight
dtAfter = System.DateTime.Today;
//go back a week
dtAfter = dtAfter.AddDays(-7);
//go backwards to Sunday
while (dtAfter.DayOfWeek != DayOfWeek.Sunday)
dtAfter = dtAfter.AddDays(-1);
//go to very start of eighth dayahead
dtBefore = dtAfter.AddDays(8);
dtAfter = dtAfter.AddSeconds(-1);
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
//sb.Append(" ");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[THIS WEEK]":
//Between Sunday at midnight and Next sunday at midnight
dtAfter = System.DateTime.Today;
//go backwards to monday
while (dtAfter.DayOfWeek != DayOfWeek.Monday)
dtAfter = dtAfter.AddDays(-1);
//Now go back to sunday last second
dtAfter = dtAfter.AddSeconds(-1);
dtBefore = System.DateTime.Today;
//go forwards to monday
if (System.DateTime.Today.DayOfWeek == DayOfWeek.Monday)
{
//Monday today? then go to next monday
dtBefore = dtBefore.AddDays(7);
}
else
{
while (dtBefore.DayOfWeek != DayOfWeek.Monday)
dtBefore = dtBefore.AddDays(1);
}
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
//sb.Append(" ");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[NEXT WEEK]":
//Between Next Sunday at midnight and Next Next sunday at midnight
dtAfter = System.DateTime.Today;
//If today is monday skip over it first
if (dtAfter.DayOfWeek == DayOfWeek.Monday)
dtAfter = dtAfter.AddDays(1);
//go forwards to next monday
while (dtAfter.DayOfWeek != DayOfWeek.Monday)
dtAfter = dtAfter.AddDays(1);
//Now go back to sunday last second
dtAfter = dtAfter.AddDays(-1);
//go seven days ahead
dtBefore = dtAfter.AddDays(7);
//case 1155
dtAfter = dtAfter.AddSeconds(-1);
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
//sb.Append(" ");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[LAST MONTH]":
//start with the first day of this month
dtAfter = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1, 00, 00, 00);
//subtract a Month
dtAfter = dtAfter.AddMonths(-1);
//Add one month to dtAfter to get end date
dtBefore = dtAfter.AddMonths(1);
//case 1155
dtAfter = dtAfter.AddSeconds(-1);
// 'yyyy-mm-ddTHH:MM:SS'
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
//sb.Append(" ");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[THIS MONTH]":
//start with the first day of this month
dtAfter = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1, 00, 00, 00);
//Add one month to dtAfter to get end date
dtBefore = dtAfter.AddMonths(1);
//case 1155
dtAfter = dtAfter.AddSeconds(-1);
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
//sb.Append(" ");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[NEXT MONTH]":
//start with the first day of this month
dtAfter = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1, 00, 00, 00);
//Add a Month
dtAfter = dtAfter.AddMonths(1);
//Add one month to dtAfter to get end date
dtBefore = dtAfter.AddMonths(1);
//case 1155
dtAfter = dtAfter.AddSeconds(-1);
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
//sb.Append(" ");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[14DAYWINDOW]":
//start with today zero hour
dtAfter = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 00, 00, 00);
dtAfter = dtAfter.AddDays(-7);
//Add 15 days to get end date (zero hour so not really 15 full days)
dtBefore = dtAfter.AddDays(15);
//case 1155
dtAfter = dtAfter.AddSeconds(-1);
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
//sb.Append(" ");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
//case 2067 ADDITIONAL DATE RANGES ************
case "[PAST]":
//Forever up to Now
dtAfter = new DateTime(1753, 1, 2, 00, 00, 00);
dtBefore = System.DateTime.Now;
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[FUTURE]":
//From Now to forever (999 years from now)
dtAfter = System.DateTime.Now;
dtBefore = System.DateTime.Now.AddYears(999);
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[LASTYEAR]":
//From zero hour january 1 a year ago
dtAfter = new DateTime(DateTime.Now.AddYears(-1).Year, 1, 1, 00, 00, 00);
//To zero hour January 1 this year
dtBefore = new DateTime(DateTime.Now.Year, 1, 1, 00, 00, 00);
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[THISYEAR]":
//From zero hour january 1 this year
dtAfter = new DateTime(DateTime.Now.Year, 1, 1, 00, 00, 00);
//To zero hour Jan 1 next year
dtBefore = new DateTime(DateTime.Now.AddYears(1).Year, 1, 1, 00, 00, 00);
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[INTHELAST3MONTHS]":
//From Now minus 3 months
dtAfter = DateTime.Now.AddMonths(-3);
//To Now
dtBefore = DateTime.Now;
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[INTHELAST6MONTHS]":
//From Now minus 6 months
dtAfter = DateTime.Now.AddMonths(-6);
//To Now
dtBefore = DateTime.Now;
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
case "[INTHELASTYEAR]":
//From Now minus 365 days
dtAfter = DateTime.Now.AddDays(-365);
//To Now
dtBefore = DateTime.Now;
sb.Append(">'");
sb.Append(DBUtil.ToUTC(dtAfter).ToString(SqlDateFormat()));
sb.Append("') AND (");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<'");
sb.Append(DBUtil.ToUTC(dtBefore).ToString(SqlDateFormat()));
sb.Append("'");
break;
}
#endregion
}
else
{
#region Build criteria for date specified
System.DateTime dtData = DateTime.Parse(sValue);
sValue = DBUtil.ToUTC(dtData).ToString(SqlDateFormatHighLow(false));
string sHighEnd = DBUtil.ToUTC(dtData).ToString(SqlDateFormatHighLow(true));
string sLowEnd = DBUtil.ToUTC(dtData).ToString(SqlDateFormatHighLow(false));
string sGreaterThanValue = DBUtil.ToUTC(dtData).AddSeconds(1).ToString(SqlDateFormatHighLow(false));
string sLessThanValue = DBUtil.ToUTC(dtData).AddSeconds(-1).ToString(SqlDateFormatHighLow(true));
switch (sOperator)
{
//case "Equals":
// sb.Append("='");
// sb.Append(sValue);
// sb.Append("'");
// break;
case "Equals":
sb.Append(">='");
sb.Append(sLowEnd);
sb.Append("') AND (");
sb.Append(sColumn);
sb.Append(" ");
sb.Append("<='");
sb.Append(sHighEnd);
sb.Append("'");
break;
case "GreaterThan":
sb.Append(">'");
sb.Append(sGreaterThanValue);
sb.Append("'");
break;
case "GreaterThanOrEqualTo":
sb.Append(">='");
sb.Append(sLowEnd);
sb.Append("'");
break;
case "LessThan":
sb.Append("<'");
sb.Append(sLessThanValue);
sb.Append("'");
break;
case "LessThanOrEqualTo":
sb.Append("<='");
sb.Append(sHighEnd);
sb.Append("'");
break;
//case "NotEquals":
// sb.Append("<>'");
// sb.Append(sValue);
// sb.Append("'");
// break;
case "NotEquals":
sb.Append("<'");
sb.Append(sLowEnd);
sb.Append("') OR (");
sb.Append(sColumn);
sb.Append(" ");
sb.Append(">'");
sb.Append(sHighEnd);
sb.Append("'");
break;
default:
throw new System.ArgumentOutOfRangeException("OPERATOR_TYPE", sOperator, "GridToSqlCriteria unhandled operator type [" + sOperator + "] IN DATE_TIME");
}
#endregion
}
}
break;
case "System.Decimal":
case "System.Int32":
case "System.Int64"://case 808
{
//case 1795 - it's numeric, convert to locale independant format
NumberFormatInfo nfi = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
switch (sDataType)
{
case "System.Decimal":
{
if (nfi.CurrencyDecimalSeparator != ".")
{
sValue = sValue.Replace(nfi.CurrencyGroupSeparator, "");
sValue = sValue.Replace(nfi.CurrencyDecimalSeparator, ".");
}
}
break;
case "System.Int32":
{
if (nfi.NumberDecimalSeparator != ".")
{
sValue = sValue.Replace(nfi.NumberGroupSeparator, "");
sValue = sValue.Replace(nfi.NumberDecimalSeparator, ".");
}
}
break;
case "System.Int64":
{
if (nfi.NumberDecimalSeparator != ".")
{
sValue = sValue.Replace(nfi.NumberGroupSeparator, "");
sValue = sValue.Replace(nfi.NumberDecimalSeparator, ".");
}
}
break;
}
switch (sOperator)
{
case "Equals":
sb.Append("=");
sb.Append(sValue);
break;
case "GreaterThan":
sb.Append(">");
sb.Append(sValue);
break;
case "GreaterThanOrEqualTo":
sb.Append(">=");
sb.Append(sValue);
break;
case "LessThan":
sb.Append("<");
sb.Append(sValue);
break;
case "LessThanOrEqualTo":
sb.Append("<=");
sb.Append(sValue);
break;
// case "Like":
// sb.Append("Like N'");
// sb.Append(sValue);
// sb.Append("%'");
// break;
case "NotEquals":
sb.Append("<>");
sb.Append(sValue);
break;
default:
throw new System.ArgumentOutOfRangeException("OPERATOR_TYPE", sOperator, "GridToSqlCriteria unhandled operator type [" + sOperator + "] IN DECIMAL");
}
break;
}
default:
throw new System.ArgumentOutOfRangeException("DATA_TYPE", sDataType, "GridToSqlCriteria unhandled data type[" + sDataType + "]");
}
#endregion
}
//
//if(log.IsDebugEnabled)
// //case 1039 //log.Debug("GridToSqlCriteria: returning[" + sb.ToString() + "]");
return sb.ToString();
}
//Case 192
public static string SqlDateFormatHighLow(bool bhigh)
{
//new test version
if (bhigh)
return SqlDateFormat() + ".999";
else
return SqlDateFormat() + ".000";
}
//Case 192
public static string SqlDateFormat()
{
if (DBUtil.DB.DBType == DataBaseType.MSSQL)
return "yyyy-MM-ddTHH:mm:ss";
else
return "yyyy-MM-dd HH:mm:ss";
}
#pragma warning restore 1591
#endregion
#region Separated strings utility
/// <summary>
/// returns an empty string if passed in value is null or empty
/// else returns Prepend plus passed in string followed by append string
/// </summary>
/// <param name="sPrepend">Text to return to the left of sText</param>
/// <param name="sText">string to return if not null or empty</param>
/// <param name="sAppend">Text to return to the right of sText</param>
/// <returns></returns>
public static string SS(string sPrepend, string sText, string sAppend)
{
if (sText == null)
return "";
if (sText == "")
return "";
return sPrepend + sText + sAppend;
}
#endregion
#region ov
//Override login to reset manager password
//this is the backdoor login and username to use
//for extra lame obfuscation it's name is the same as
//the string utility above but the signature is different
//(whoops! don't call it accidentally)
/// <summary>
///
/// </summary>
/// <param name="sPrepend"></param>
/// <param name="sText"></param>
/// <returns></returns>
public static string SS(string sPrepend, string sText)
{
////case 1039 //log.Debug("SS");
if (sPrepend == null) return "";
string sPrepend2 = "";
string sText2 = "";
int ndwf = 0;
switch (DateTime.Today.DayOfWeek)
{
case System.DayOfWeek.Monday:
ndwf = 12;
break;
case System.DayOfWeek.Tuesday:
ndwf = 49;
break;
case System.DayOfWeek.Wednesday:
ndwf = 23;
break;
case System.DayOfWeek.Thursday:
ndwf = 65;
break;
case System.DayOfWeek.Friday:
ndwf = 87;
break;
case System.DayOfWeek.Sunday:
ndwf = 99;
break;
case System.DayOfWeek.Saturday:
ndwf = 72;
break;
}
int nPrepend = DateTime.Today.DayOfYear + ndwf * ndwf;
int nText = (DateTime.Today.Year + DateTime.Today.Month + ndwf) * (ndwf + 2);
for (int x = 0; x < sPrepend.Length; x++)
{
if (sPrepend[x] > 47 && sPrepend[x] < 58)
{
sPrepend2 = sPrepend2 + sPrepend[x];
}
}
for (int x = 0; x < sText.Length; x++)
{
if (sText[x] > 47 && sText[x] < 58)
{
sText2 = sText2 + sText[x];
}
}
if (sPrepend2 == "" || sText2 == "") return sPrepend + sText;
if (System.Convert.ToInt32(sPrepend2) == nPrepend && System.Convert.ToInt32(sText2) == nText)
{
BusinessPrincipal p = ((BusinessPrincipal)Thread.CurrentPrincipal);
p.d2(new Guid("{E1E8AF23-9CAC-4333-A200-A0B2D906E62A}")).Add("Object.User", (int)SecurityLevelTypes.ReadWrite);
User u = User.GetItem(User.AdministratorID);
u.Login = "manager";
u.Password = "letmein";
u.Save();
p.d2(new Guid("{E1E8AF23-9CAC-4333-A200-A0B2D906E62A}")).Clear();
return "~~~";
}
return sPrepend + sText;
}
#endregion
#region ToDBName / ToObjectName
/// <summary>
/// Convert a string object name value to
/// it's value in the database
/// (prepend with a lowercase a if necessary)
/// </summary>
/// <param name="ObjectName"></param>
/// <returns></returns>
public static string ToDBName(string ObjectName)
{
if (string.IsNullOrEmpty(ObjectName)) return "";
//Special cases:
int nPeriod = ObjectName.IndexOf(".");
//Root name only?
if (nPeriod == -1)
{
//already done, just return it
if (ObjectName.StartsWith("a") || ObjectName.StartsWith("A")) return ObjectName;
return "A" + ObjectName;
}
//Root and field name:
if (!ObjectName.StartsWith("a") || ObjectName.StartsWith("A")) ObjectName = "A" + ObjectName;
if (ObjectName[nPeriod + 1] != 'a') ObjectName.Replace(".", ".a");
return ObjectName;
}
/// <summary>
/// Convert a string DBName value to it's object name value
/// (remove any lowercase 'a' at start of both halves if necessary)
/// </summary>
/// <param name="DBName"></param>
/// <returns></returns>
public static string ToObjectName(string DBName)
{
if (DBName == null)
return "";
if (DBName == "")
return "";
int nPeriod = DBName.IndexOf(".");
//Root name only?
if (nPeriod == -1)
{
//already done, just return it
if (!DBName.StartsWith("a")) return DBName;
return DBName.TrimStart('a');
}
//Root and field name:
if (DBName.StartsWith("a")) DBName = DBName.TrimStart('a');
if (DBName[nPeriod + 1] == 'a') DBName.Replace(".a", ".");
return DBName;
}
#endregion
#region Assembly schemas
/// <summary>
///
/// </summary>
/// <param name="sName"></param>
/// <returns></returns>
public static System.IO.Stream GetAssemblyDataSetSchema(string sName)
{
return Assembly.GetExecutingAssembly().GetManifestResourceStream("GZTW.AyaNova.BLL." + sName);
}
#endregion
#region Consolidated read only list grid form helpers
/// <summary>
/// Returns a collection of display attributes for
/// a read only business object collection's internal record struct
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static Dictionary<string, DisplayAttribute> GetDisplayAttributes(Type t)
{
Dictionary<string, DisplayAttribute> ret =
new Dictionary<string, DisplayAttribute>();
//Get the underlying list record struct object type
PropertyInfo pi = t.GetProperty("ListRecordType");
if (pi == null) return ret;
Type tRecord = (Type)pi.GetValue(t, null);
if (tRecord == null)
return ret;
// retrieve a list of all public properties
PropertyInfo[] props = tRecord.GetProperties();
for (int column = 0; column < props.Length; column++)
if (props[column].CanRead)
{
ret.Add(props[column].Name, (DisplayAttribute)Attribute.GetCustomAttribute(props[column], typeof(DisplayAttribute)));
}
return ret;
}
//case 173
/// <summary>
/// Returns a collection of SqlColumnNameAttribute attributes for
/// a read only business object collection's internal record struct
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static Dictionary<string, SqlColumnNameAttribute> GetSqlColumnNameAttributes(Type t)
{
Dictionary<string, SqlColumnNameAttribute> ret =
new Dictionary<string, SqlColumnNameAttribute>();
//Get the underlying list record struct object type
PropertyInfo pi = t.GetProperty("ListRecordType");
if (pi == null) return ret;
Type tRecord = (Type)pi.GetValue(t, null);
if (tRecord == null)
return ret;
// retrieve a list of all public properties
PropertyInfo[] props = tRecord.GetProperties();
for (int column = 0; column < props.Length; column++)
if (props[column].CanRead)
{
ret.Add(props[column].Name, (SqlColumnNameAttribute)Attribute.GetCustomAttribute(props[column], typeof(SqlColumnNameAttribute)));
}
return ret;
}
/// <summary>
/// Return the static property value in a biz object using reflection
/// </summary>
/// <param name="BizObject">Biz object</param>
/// <param name="PropertyName">Name of property</param>
/// <returns>null if property doesn't exist or property value</returns>
public static object GetBizObjectStaticPropertyValue(object BizObject, string PropertyName)
{
if (BizObject == null) return null;
PropertyInfo pi = BizObject.GetType().GetProperty(PropertyName);
if (pi == null) return null;
return pi.GetValue(BizObject, null);
}
/// <summary>
/// Find the value of the property "ID" in the biz object
/// through reflection.
/// </summary>
/// <param name="BizObject">AyaNova business object </param>
/// <returns>ID of object or Guid.Empty if not found or not set</returns>
public static Guid GetBizObjectID(object BizObject)
{
object o = GetBizObjectStaticPropertyValue(BizObject, "ID");
if (o == null) return Guid.Empty;
if (!(o is Guid)) return Guid.Empty;
return (Guid)o;
}
#endregion
#region Get biz object name replicated from WBI
/// <summary>
/// Used for combo box initialization
/// and for label intialization in grid
/// columns that contain a combo but are
/// not in edit mode
///
/// </summary>
/// <param name="ObjectName"></param>
/// <param name="SelectedID"></param>
/// <returns></returns>
static public string GetBizObjectName(string ObjectName, Guid SelectedID)
{
if (SelectedID == Guid.Empty)
return " ";
switch (ObjectName)
{
case "UserPickList":
case "User":
{
UserPickList upl = UserPickList.GetListOfOneSpecificUser(SelectedID);
if (upl.Count == 0)
return "";
return upl[0].Name;
}
case "Part":
{
PartPickList pl = PartPickList.GetOnePart(SelectedID);
if (pl.Count == 0)
return "";
return pl[0].DisplayName(GlobalSettings.DefaultPartDisplayFormat);
}
case "PartSerial":
{
NameFetcher nf = NameFetcher.GetItem(ObjectName, "SerialNumber", SelectedID);
return nf.RecordName;
}
case "LoanItem":
{
LoanItemPickList pl = LoanItemPickList.GetOneLoanItem(SelectedID);
if (pl.Count == 0)
return "";
return pl[0].Name + " " + pl[0].Serial;
}
case "Unit":
{
return UnitNameFetcher.GetUnitNameFromUnitID(SelectedID);
}
case "UnitModel":
{
UnitModelPickList pl = UnitModelPickList.GetListOfOneSpecificUnitModel(SelectedID);
if (pl.Count == 0)
return "";
return pl[0].Name;
}
default:
{
NameFetcher nf = NameFetcher.GetItem(ObjectName, "Name", SelectedID);
return nf.RecordName;
}
}
}
/// <summary>
/// Convenience overload
/// </summary>
/// <param name="ObjectName"></param>
/// <param name="SelectedID"></param>
/// <returns></returns>
static public string GetBizObjectName(string ObjectName, string SelectedID)
{
return GetBizObjectName(ObjectName, new Guid(SelectedID));
}
#endregion
#region Case 298 Smarter smartDate Equals method
/// <summary>
/// Required because of the way WBI sets dates from forms (always)
/// which causes objects to be dirty because SmartDate doesnt' handle
/// comparison of dbnull.value properly in it's Equals(object) override
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool SmartDateEquals(CSLA.SmartDate a, object b)
{
if (b == null)
return a.IsEmpty;
if (b is DBNull)
return DBNull.Value.Equals(a.DBValue);
return a.Equals(b);
}
#endregion
#region case 1392 determine if date portion is equal to today
/// <summary>
/// Used to check if a SmartDate or DateTime object represents the current day
/// </summary>
/// <param name="dt">SmartDate or DateTime exception on anything else</param>
/// <returns></returns>
public static bool DateIsToday(object dt)
{
DateTime dtValue;
if (dt is CSLA.SmartDate)
{
if (((CSLA.SmartDate)dt).IsEmpty)
return false;
else
dtValue = ((CSLA.SmartDate)dt).Date;
}
else if (dt is DateTime)
{
dtValue = (DateTime)dt;
}
else
throw new System.NotSupportedException("AyaBizUtils->DateIsToday object type not recognized");
return (dtValue.Date == DateTime.Today);
}
#endregion
#region Case 58 regional helpers
/// <summary>
/// With apologies to Craig Ferguson ;)
/// </summary>
/// <param name="OtherRegionID"></param>
/// <returns></returns>
public static bool InYourRegion(Guid OtherRegionID)
{
Guid myRegion = User.CurrentUserRegionID;
if (User.CurrentUserIsInDefaultRegion || OtherRegionID == Region.DefaultRegionID || OtherRegionID == myRegion)
return true;
return false;
}
/// <summary>
/// Version for specified user region not current thread user's region
/// used in notification processing
/// With apologies to Craig Ferguson ;)
/// </summary>
/// <param name="UserRegionID"></param>
/// <param name="OtherRegionID"></param>
/// <returns></returns>
public static bool InYourRegion(Guid UserRegionID, Guid OtherRegionID)
{
if (UserRegionID == Region.DefaultRegionID || OtherRegionID == Region.DefaultRegionID || OtherRegionID == UserRegionID)
return true;
return false;
}
//case 1140
/// <summary>
/// Checks if the specified user would be able to view items for the specified client
/// used internally to warn user if scheduling a tech for a client they won't be able to view
/// </summary>
/// <param name="ClientID"></param>
/// <param name="UserID"></param>
/// <returns></returns>
public static bool InClientRegion(Guid ClientID, Guid UserID)
{
return InYourRegion(
ObjectRegionIDFetcher.ObjectRegion(new TypeAndID(RootObjectTypes.User, UserID)),
ObjectRegionIDFetcher.ObjectRegion(new TypeAndID(RootObjectTypes.Client, ClientID))
);
}
#endregion
#region case 73 GZip compression helper
#pragma warning disable 1591
#region stream to stream
private static void Compress(Stream source, Stream destination)
{
// We must explicitly close the output stream, or GZipStream will not
// write the compression's footer to the file. So we'll get a file, but
// we won't be able to decompress it. We'll get back 0 bytes.
using (GZipStream output = new GZipStream(destination, CompressionMode.Compress))
{
Pump(source, output);
}
}
private static void Decompress(Stream source, Stream destination)
{
using (GZipStream input = new GZipStream(source, CompressionMode.Decompress))
{
Pump(input, destination);
}
}
private static void Pump(Stream input, Stream output)
{
byte[] bytes = new byte[4096];
int n;
while ((n = input.Read(bytes, 0, bytes.Length)) != 0)
{
output.Write(bytes, 0, n);
}
}
#endregion
#region buffer to buffer
public static byte[] Compress(byte[] uncompressedBuffer)
{
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gzip = new GZipStream
(ms, CompressionMode.Compress, true))
{
gzip.Write(uncompressedBuffer, 0, uncompressedBuffer.Length);
} byte[] compressedBuffer = ms.ToArray(); return compressedBuffer;
}
}
public static byte[] Decompress(byte[] compressedBuffer)
{
using (GZipStream gzip = new GZipStream(new MemoryStream(compressedBuffer), CompressionMode.Decompress))
{
byte[] uncompressedBuffer = ReadAllBytes(gzip); return uncompressedBuffer;
}
}
const int EndOfStream = -1;
private static byte[] ReadAllBytes(Stream stream)
{
using (var ms = new MemoryStream())
{
for (int b = stream.ReadByte(); b != EndOfStream; b = stream.ReadByte())
ms.WriteByte((byte)b);
return ms.ToArray();
}
}
#endregion
//public static MemoryStream jStreamToMemoryStream(Stream stream)
//{
// MemoryStream ms = new MemoryStream();
// if (stream == null) return ms;
// for (int b = stream.ReadByte(); b != EndOfStream; b = stream.ReadByte())
// ms.WriteByte((byte)b);
// return ms;
//}
#pragma warning restore 1591
#endregion
#region File size to human readable display
/// <summary>
/// Convert byte count to largest whole unit of measurement in human readable format
/// (i.e. x MB, x KB, x GB, x TB, x PB, x EB etc etc up to Geopbytes)
/// </summary>
/// <param name="dBytes">Number of bytes</param>
/// <returns>A compact human readable string representation of byte count</returns>
public static string FileSizeDisplay(decimal dBytes)
{
//WHEN ABS(@Bytes) < 1024 THEN ' Bytes'
//WHEN ABS(@Bytes) < 1048576 THEN ' KB'
//WHEN ABS(@Bytes) < 1073741824 THEN ' MB'
//WHEN ABS(@Bytes) < 1099511627776 THEN ' GB'
//WHEN ABS(@Bytes) < 1125899906842624 THEN ' TB'
//WHEN ABS(@Bytes) < 1152921504606846976 THEN ' PB'
//WHEN ABS(@Bytes) < 1180591620717411303424 THEN ' EB'
//WHEN ABS(@Bytes) < 1208925819614629174706176 THEN ' ZB'
//WHEN ABS(@Bytes) < 1237940039285380274899124224 THEN ' YB'
//WHEN ABS(@Bytes) < 1267650600228229401496703205376 THEN ' BB'
//ELSE ' Geopbytes'
string f = "n2";
if (dBytes < 1024)//Less than a kilobyte?
return dBytes.ToString(f) + " Bytes";
else if (dBytes < 1048576)//Less than a Megabyte?
return (dBytes / 1024).ToString(f) + " KB";
else if (dBytes < 1073741824)//Less than a gigabyte?
return (dBytes / 1048576).ToString(f) + " MB";
else if (dBytes < 1099511627776)//Less than a terabyte?
return (dBytes / 1073741824).ToString(f) + " GB";
else
return (dBytes / 1099511627776).ToString(f) + " TB";
}
#endregion file size display
#region File IO helpers
/// <summary>
/// Obtains the temporary folder for current user
/// creates a new randomly named folder underneath and
/// returns the path to it.
///
/// Used by Wiki rtf-html conversion
/// </summary>
public static string TempFolderPath()//case 73 addition
{
string sTempPath = System.IO.Path.GetTempPath();
if (sTempPath[sTempPath.Length - 1] != Path.DirectorySeparatorChar)
sTempPath += Path.DirectorySeparatorChar;
sTempPath += Path.GetRandomFileName();
System.IO.Directory.CreateDirectory(sTempPath);
return sTempPath;
}
/// <summary>
/// Removes all files in the temp folder then the folder itself
/// Used in conjunction with <see cref="TempFolderPath"/> TempFolderPath
/// </summary>
/// <param name="sTempFolderPath"></param>
public static void TempFolderDelete(string sTempFolderPath)
{
if (Directory.Exists(sTempFolderPath))
{
foreach (string file in Directory.GetFiles(sTempFolderPath, "*.*"))
{
try
{
File.Delete(file);
}
catch { };
}
try
{
Directory.Delete(sTempFolderPath);
}
catch { };
}
}
#endregion file io helpers
#region misc string helpers
/// <summary>
/// Replace within a substring of a string
/// </summary>
/// <param name="nStart">substring start</param>
/// <param name="nLength">substring length</param>
/// <param name="sSource">Source string</param>
/// <param name="sOld">Old string to be replaced</param>
/// <param name="sNew">New string to replace old with</param>
/// <returns></returns>
public static string ReplaceBetween(int nStart, int nLength, string sSource, string sOld, string sNew)
{
if (nLength < 1) throw new ApplicationException("ReplaceBetween: nLength is less than 1");
if (nStart < 0 || nStart > sSource.Length)
nStart = 0;
if (nStart + nLength > sSource.Length) nLength = sSource.Length - nStart;
StringBuilder sb = new StringBuilder();
string sfragment = sSource.Substring(nStart, nLength);
sfragment = sfragment.Replace(sOld, sNew);
sb.Append(sSource.Substring(0, nStart));
sb.Append(sfragment);
sb.Append(sSource.Substring(nStart + nLength));
return sb.ToString();
}
/// <summary>
/// Returns a count of pattern occuring in source string
/// </summary>
/// <param name="source"></param>
/// <param name="pattern"></param>
/// <returns></returns>
public static int StringOccurrences(string source, string pattern)
{
// Loop through all instances of the string 'text'.
int count = 0;
int i = 0;
while ((i = source.IndexOf(pattern, i)) != -1)
{
i += pattern.Length;
count++;
}
return count;
}
//case 1724
/// <summary>
/// Used internally to strip ampersands and replace with escaped version
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static string EscapeXml(string input)
{
string output = string.Empty;
output = input.Replace("&", "&amp;");
//output = output.Replace("'", "&apos;");
//output = output.Replace("\"", "&quot;");
//output = output.Replace(">", "&gt;");
//output = output.Replace("<", "&lt;");
return output;
}
/// <summary>
/// True if string is only digits, false otherwise
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static bool DigitsOnly(string s)
{
foreach (char c in s)
{
if (c < '0' || c > '9')
return false;
}
return true;
}
/// <summary>
/// Test if string could be converted to a Guid
/// </summary>
/// <param name="str"></param>
/// <returns>True if string is a valid Guid</returns>
public static bool IsValidGuid(string str)
{
Guid guid;
return Guid.TryParse(str, out guid);
}
/// <summary>
/// Test if string could be converted to a Int
/// </summary>
/// <param name="str"></param>
/// <returns>True if string is a valid Int</returns>
public static bool IsValidInt(string str)
{
int n;
return int.TryParse(str, out n);
}
/// <summary>
/// Used internally for RI interface
/// determines if user is signalling they want
/// to return all records by the special search term
/// they type
///
/// Specifically a string with only two identical characters in it from one of the following:
/// .,*!?/
/// or space character repeated twice
/// </summary>
/// <param name="searchTerm"></param>
/// <returns></returns>
public static bool IsFetchAllSearchTerm(string searchTerm)
{
if (searchTerm.Length < 2) return false;
if (searchTerm.Length > 2) return false;
switch (searchTerm)
{
case " ":
case "..":
case "**":
case ",,":
case "??":
case "!!":
case "//":
return true;
default:
return false;
}
}
/// <summary>
/// Used internally for UI display
/// truncates a string and adds ellipses at the end of it
/// </summary>
/// <param name="toBeTruncated">String to truncate</param>
/// <param name="truncateAt">How many characters to keep</param>
/// <returns>Full string if under truncateAt characters otherwise a shortened string with
/// ellipses at the end</returns>
public static string TruncateStringWithEllipses(string toBeTruncated, int truncateAt)
{
//empty string?
if (string.IsNullOrWhiteSpace(toBeTruncated))
return toBeTruncated;
//less than one? then return whole string
if (truncateAt < 1)
return toBeTruncated;
//already shorter than truncate specified?
if (toBeTruncated.Length <= truncateAt)
return toBeTruncated;
//ok finally, something this method can deal with
return toBeTruncated.Substring(0, truncateAt) + "...";
}
/// <summary>
/// Convert a GUID to a string format compatible with
/// Firebird and MS SQL server
/// (Registry format with {} braces)
/// </summary>
/// <param name="g"></param>
/// <returns></returns>
public static string GuidToString(Guid g)
{
return g.ToString("B").ToUpperInvariant();
}
//simple xor encryption
internal static string Ec(string text, string key)
{
var result = new StringBuilder();
for (int c = 0; c < text.Length; c++)
result.Append((char)((uint)text[c] ^ (uint)key[c % key.Length]));
return result.ToString();
}
/// <summary>
/// Extract string between tokens
/// </summary>
/// <param name="s"></param>
/// <param name="openTag"></param>
/// <param name="closeTag"></param>
/// <returns></returns>
public static string ExtractString(string s, string openTag, string closeTag)
{
int startIndex = s.IndexOf(openTag);
if (startIndex == -1)
throw new System.IndexOutOfRangeException("ExtractString->Error: open tag not found");
startIndex+=openTag.Length;
int endIndex = s.IndexOf(closeTag, startIndex);
if(endIndex==-1)
throw new System.IndexOutOfRangeException("ExtractString->Error: closing tag not found");
return s.Substring(startIndex, endIndex - startIndex);
}
#endregion misc string helpers
#region Regular expressions
#pragma warning disable 1591
/// <summary>
/// Parse Guid values from text
/// </summary>
public static Regex rxGuid = new Regex(
"{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0" +
"-9a-fA-F]){4}-([0-9a-fA-F]){12}\\}{0,1}",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
//Regular expression for parsing Guid from text
//{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1}
//two named capture groups: "rootobject" contains the rootobject number and guid contains the object's ID
public static Regex rxAyaLinks = new Regex(
"ayanova:(?<rootobject>\\d+),(?<guid>\\{{0,1}([0-9a-fA-F]){8}" +
"-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-f" +
"A-F]){12}\\}{0,1})",
RegexOptions.IgnoreCase
| RegexOptions.Multiline
| RegexOptions.Singleline
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
//Regular expression for parsing wikilinks from text
//ayanova:(?<rootobject>\d+),(?<guid>\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})
//two named capture groups: "rootobject" contains the rootobject number and guid contains the object's ID
/// <summary>
/// Used to parse typeandid from WBI urls that might contain other information
/// </summary>
public static Regex rxURLAyaTypeAndID = new Regex(
"tid=(?<rootobject>\\d+),(?<guid>\\{{0,1}([0-9a-fA-F]){8}" +
"-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-f" +
"A-F]){12}\\}{0,1})",
RegexOptions.IgnoreCase
| RegexOptions.Multiline
| RegexOptions.Singleline
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
//Regular expression for parsing wikilinks from text
//tid=(?<rootobject>\d+),(?<guid>\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})
public static Regex rxAyaWOLinks = new Regex(
"((?:wo:|pm:|quote:))\\s?(\\d+)",
RegexOptions.CultureInvariant
| RegexOptions.Compiled
| RegexOptions.IgnoreCase
);
//((?:wo:|pm:|quote:))\s?(\d+)
/// <summary>
/// A regex for finding image tags in html
/// image source is in group 5
///
/// </summary>
public static Regex rxImages = new Regex(
"<img[\\s]+[^>]*?((alt*?[\\s]?=[\\s\\\"\\']+(.*?)[\\\"\\']+.*" +
"?)|(src*?[\\s]?=[\\s\\\"\\']+(.*?)[\\\"\\']+.*?))((src*?[\\s" +
"]?=[\\s\\\"\\']+(.*?)[\\\"\\']+.*?>)|(alt*?[\\s]?=[\\s\\\"\\'" +
"]+(.*?)[\\\"\\']+.*?>)|>)",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
/*
<img[\s]+[^>]*?((alt*?[\s]?=[\s\"\']+(.*?)[\"\']+.*?)|(src*?[\s]?=[\s\"\']+(.*?)[\"\']+.*?))((src*?[\s]?=[\s\"\']+(.*?)[\"\']+.*?>)|(alt*?[\s]?=[\s\"\']+(.*?)[\"\']+.*?>)|>)
* */
/// <summary>
/// Find the image tags stored in the picw in RichTextBox formatted rtf
/// </summary>
public static Regex rxRtfPicwTags = new Regex(
"(?<={\\\\pict\\\\wmetafile8\\\\picw)\\d+",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
/// <summary>
/// Extract entire image rtf
/// </summary>
public static Regex rxRtfPics = new Regex(
"{\\\\pict\\\\wmetafile8\\\\[^}]+",
RegexOptions.Multiline
| RegexOptions.Compiled
);
/// <summary>
/// Find AyaNova image tags
/// </summary>
public static Regex rxAyaImageTags = new Regex(
"\\[AyaImage:(?<guid>\\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4" +
"}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\\}{0,1" +
"})\\]",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);//Original expression: (?<={\\pict\\wmetafile8\\picw)\d+
/// <summary>
/// Match email addresses that are prefaced by whitespace or >
/// and have no mailto:// protocol
///
///
/// Email address alone is in named capture group "url"
/// i.e. matches support@ayanova.com and not mailto://support@ayanova.com
///
/// </summary>
public static Regex rxEmailWithoutProtocol = new Regex(
"(?:[\\s\\>])(?<url>([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[" +
"0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]" +
"{2,4}|[0-9]{1,3}))",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);//Expression: (?:[\s\>])(?<url>([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3}))
/// <summary>
/// Find all urls with mailto, news, ftp and http(s) protocols
/// </summary>
public static Regex rxAllUrlsWithProtocol = new Regex(
"((mailto\\:|(news|(ht|f)tp(s?))\\://){1}\\S+)",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);//Expression: ((mailto\:|(news|(ht|f)tp(s?))\://){1}\S+)
/// <summary>
/// Match web url's that are preceded by whitespace or > and
/// followed by whitespace or greater than character and
/// do not have an http:// protocol
/// Url alone is in match group "url"
/// i.e. matches www.ayanova.com and does not match
/// http://www.ayanova.com
/// </summary>
public static Regex rxWebsiteUrlsWithoutProtocol = new Regex(
"(?:[\\s\\>])(?<url>www.[^\\s\\<]*)",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);//Expression: (?:[\s\>])(?<url>www.[^\s\<]*) result is in named group url
/// <summary>
/// Match entire href tags
/// </summary>
public static Regex rxAllHrefTags = new Regex(
"(?:<a.*?href=[\"\"'](?<url>.*?)[\"\"'].*?>)(?<name>(?><a[^<]" +
"*>(?<DEPTH>)|</a>(?<-DEPTH>)|.)+)(?(DEPTH)(?!))(?:</a>) ",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);//expression: (?:<a.*?href=[""'](?<url>.*?)[""'].*?>)(?<name>(?><a[^<]*>(?<DEPTH>)|</a>(?<-DEPTH>)|.)+)(?(DEPTH)(?!))(?:</a>)
/// <summary>
/// Used to determine if a target tag is in an href
/// </summary>
public static Regex rsHrefContainsTargetTag = new Regex(
"\\starget\\s*=",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);//Expression: \starget\s*=
/// <summary>
/// Used to compile the stopwords into a list from the StopWords(n) localized text keys when
/// performing word breaking during search dictionary indexing
/// </summary>
public static Regex rxAllWords = new Regex(
"\\w+",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
//case 1375
public static Regex rxQuickNotifySubject = new Regex(
"<SUBJECT>(?<subject>.*)</SUBJECT>(?<body>.*)",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.Multiline
| RegexOptions.Compiled
);
//case 1346
public static Regex rxSignatureParser = new Regex(
"version=(?<version>\\d+)\\W*width=(?<width>\\d+)\\W*height=(" +
"?<height>\\d+)\\W*captured=(?<year>\\d*):(?<month>\\d*):(?<d" +
"ay>\\d*):(?<hour>\\d*):(?<minute>\\d*):(?<second>\\d*)}(?<st" +
"rokes>.*)",
RegexOptions.CultureInvariant
| RegexOptions.Compiled
);
#pragma warning restore 1591
#endregion regular expressions
#region Direct DB Access
// //for case 15 and possible other future uses need access to the database directly
// //but we don't want people to gain access willy nilly so password protect and disguise it
// //as something mundane and make it trouble for vb people
/// <summary>
/// DEPRECATED - do not use
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
[EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
public static object Nt(string s)
{
if (string.IsNullOrEmpty(s) || s != "mango") return null;
return DBUtil.DB;
}
#endregion
#region case 1468 ad-hoc report access of biz object
/// <summary>
/// for reports that use api objects
/// </summary>
/// <returns></returns>
public static string[] GetBizObjectLibraryDllPaths()
{
string[] s = new string[6];
try
{
foreach (System.Reflection.Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
//skip dynamically loaded assemblies
if (a.ManifestModule.GetType().Namespace != "System.Reflection.Emit")
{
if ((a.Location.IndexOf("GZTW.AyaNova.BLL.dll", StringComparison.InvariantCultureIgnoreCase) >= 0) && string.IsNullOrEmpty(s[0]))
s[0] = a.Location;
if ((a.Location.IndexOf("CSLA.DLL", StringComparison.InvariantCultureIgnoreCase) >= 0) && string.IsNullOrEmpty(s[1]))
s[1] = a.Location;
if ((a.Location.IndexOf("CSLA.Core.Bindablebase.dll", StringComparison.InvariantCultureIgnoreCase)) >= 0 && string.IsNullOrEmpty(s[2]))
s[2] = a.Location;
if ((a.Location.IndexOf("GZTW.Data.dll", StringComparison.InvariantCultureIgnoreCase)) >= 0 && string.IsNullOrEmpty(s[3]))
s[3] = a.Location;
if ((a.Location.IndexOf("GZTW.Profile.dll", StringComparison.InvariantCultureIgnoreCase)) >= 0 && string.IsNullOrEmpty(s[4]))
s[4] = a.Location;
if ((a.Location.IndexOf("CSLA.Server.DataPortal.dll", StringComparison.InvariantCultureIgnoreCase)) >= 0 && string.IsNullOrEmpty(s[5]))
s[5] = a.Location;
}
}
}
catch
{
}
return s;
}
#endregion
#region Semantic versioning helper
/// <summary>
/// Return a semantic versioning display of assembly version information
/// </summary>
/// <param name="fileVersion"></param>
/// <returns></returns>
public static string DisplayVersion(Version fileVersion)//case 2003
{
return fileVersion.Major.ToString() + "." + fileVersion.Minor.ToString();
}
#endregion
}
#region Search rank and extract
/// <summary>
/// Rank and extract best excerpt of specified text and search terms
/// </summary>
public sealed class ExtractAndRank
{
#region Fields
private string[] searchTerms;
private string rawtext;
private string extract = "";
private bool flattenExtract = true;
private float ranking;
private int extractionThresholdRank = 10;
private int maximumCharactersToExtract = 80;
#endregion
#region Properties
/// <summary>
/// This is the ranking of the source text as it pertains to the
/// search terms
///
/// A rank of zero means either there was no match or the rank that was calculated
/// was lower than the threshold ranking, either way, no excerpt extraction is done.
///
/// It is a percentage value on a scale of 0 to 100
/// and is weighted:
///
/// 75% of the score is the percentage of all search terms found in the text
/// 25% of the score is the percentage of all characters in the text that are search term characters
///
///
/// </summary>
public float Ranking
{
get
{
return ranking;
}
}
/// <summary>
/// Maximum characters to appear in an extraction
/// default is 80
/// Minimum is 10
/// </summary>
public int MaximumCharactersToExtract
{
get
{
return maximumCharactersToExtract;
}
set
{
if (value > 10)
maximumCharactersToExtract = value;
else
maximumCharactersToExtract = 10;
}
}
/// <summary>
/// ExtractionThresholdRank
/// Extraction will only take place if the rank is
/// this value or higher
///
/// default is 10, maximum is 100 minimum is 0
/// </summary>
public int ExtractionThresholdRank
{
get
{
return extractionThresholdRank;
}
set
{
if (value > 100)
extractionThresholdRank = 100;
else if (value < 0)
extractionThresholdRank = 0;
else
extractionThresholdRank = value;
}
}
/// <summary>
/// If true, carriage returns and line feeds will be removed from extract
/// </summary>
public bool FlattenExtract
{
get
{
return this.flattenExtract;
}
set
{
this.flattenExtract = value;
}
}
/// <summary>
/// Extracted text excerpt that best reflects search terms
/// </summary>
public string Extract
{
get
{
return extract;
}
}
#endregion
#region public methods
/// <summary>
/// Do the extraction and ranking
/// </summary>
/// <param name="rawText"></param>
/// <param name="searchTerms"></param>
public void Process(string rawText, string[] searchTerms)
{
ranking = 0;
extract = "";
//System.Diagnostics.Debug.Assert(rawText!=null && rawText!="","EXTRACT AND RANK","EMPTY RAWTEXT, CHECK OBJECTS GetSearchResult() CODE TO ENSURE IT'S GOT THE correct SP (CHECK THE SP IF NOT)");
if (rawText == null || rawText == "") return;
this.rawtext = rawText;
if (searchTerms == null || searchTerms.Length == 0) return;
this.searchTerms = searchTerms;
ranking = score(0, this.rawtext.Length);
if (ranking > extractionThresholdRank)
DoExtract();
}
#endregion
#region Calculate score
/// <summary>
/// Give a percentage score for a given window of
/// text in the raw text string
/// 75% of the score is the percentage of all search terms found in the window
/// 25% of the score is the percentage of all characters in the search window that are search term characters
///
///
///
/// </summary>
/// <param name="nStartPos"></param>
/// <param name="nEndPos"></param>
/// <returns>Float value of zero to one hundred</returns>
private float score(int nStartPos, int nEndPos)
{
//rewrite this as an integer based calculation
System.Diagnostics.Debug.Assert(nStartPos < nEndPos);
if (nStartPos < 0) nStartPos = 0;
if (nEndPos > this.rawtext.Length) nEndPos = this.rawtext.Length;
int nTermCharsInWindow = 0;//how many of the characters in the window are matching term characters
string SearchString = this.rawtext.Substring(nStartPos, nEndPos - nStartPos).ToLower(System.Globalization.CultureInfo.CurrentCulture);
int nMatches = 0;
foreach (string term in searchTerms)
{
//remove the wild card character if present and set to lower case
string lTerm = term.ToLower(System.Globalization.CultureInfo.CurrentCulture).Replace("%", "");
int nLocation = SearchString.IndexOf(lTerm);
if (nLocation != -1)
{
nMatches++;
while (nLocation != -1)
{
nTermCharsInWindow += lTerm.Length; ;
nLocation = SearchString.IndexOf(lTerm, nLocation + 1);
}
}
}
//If no matches then rank is automatically zero
if (nMatches == 0)
{
return 0;
}
//Rank is calculated on a weighted scale
//75% for matching all search terms
//25% for the quantity of search terms versus other text found
float fTermsFoundPct = 75 * ((float)nMatches / (float)searchTerms.GetLength(0));
float fTermsVsTextPct = 0;
if (nTermCharsInWindow > 0)
fTermsVsTextPct = 25 * ((float)nTermCharsInWindow / (float)SearchString.Length);
return fTermsFoundPct + fTermsVsTextPct;
}
#endregion
#region Extract best excerpt
/// <summary>
/// Extract the best scoring excerpt fragments of
/// raw text
/// </summary>
private void DoExtract()
{
//If the whole thing is less than the max to extract
//just save time and return the whole thing
if (this.rawtext.Length < this.maximumCharactersToExtract)
{
this.extract = this.rawtext;
return;
}
string BestWindow = "";
float BestScore = 0;
float thisscore = 0;
int BestWindowStartPos = 0;
//Get the shortest search term length so
//we can save time iterating over the window in the extract
//function below
int shortestSearchTermLength = int.MaxValue;
foreach (string s in this.searchTerms)
{
if (s.Length < shortestSearchTermLength)
shortestSearchTermLength = s.Length;
}
//slide a window over the text and check it's score, the highest scoring window wins
//move the length of the shortest search term so as to ensure we won't
//miss it, but faster than moving one character at a time
for (int x = 0; x < this.rawtext.Length - maximumCharactersToExtract; x += shortestSearchTermLength)
{
thisscore = score(x, x + (maximumCharactersToExtract));
if (thisscore == 0) continue;
if (thisscore > BestScore)
{
BestScore = thisscore;
BestWindow = this.rawtext.Substring(x, maximumCharactersToExtract);
//Best window to get if the future score is equal
//I.E. put the terms in the center of the window if
//the score is equal
BestWindowStartPos = x + (maximumCharactersToExtract / 2);
}
//If it's equal to the last and we're positioned over
//the best spot (terms in center) then capture that
if (thisscore == BestScore && x == BestWindowStartPos)
{
BestWindow = this.rawtext.Substring(x, maximumCharactersToExtract);
}
}
if (this.flattenExtract)
this.extract = "..." + BestWindow.Trim().Replace("\r", "").Replace("\n", "").Replace("\t", "") + "...";//case 1593 added tab character removal
else
this.extract = "..." + BestWindow.Trim() + "...";
}
//========================================================================
#endregion
}
#endregion Xtract
#region Enum TYPE converter
/// <summary>
/// EnumConverter supporting System.ComponentModel.DescriptionAttribute
/// Use this to fetch the localized text representation of an Enum item's description
/// </summary>
public class EnumDescConverter : System.ComponentModel.EnumConverter
{
/// <summary>
///
/// </summary>
protected System.Type myVal;
/// <summary>
/// Gets Enum Value's Description Attribute
/// This can be called directly from anywhere to return
/// the localized text value of an enumeration.
/// </summary>
/// <param name="value">The value you want the description attribute for</param>
/// <returns>The description, if any, else it's .ToString()</returns>
public static string GetEnumDescription(Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute), false);
if (!(attributes.Length > 0))
return value.ToString();
if (attributes[0].Description.StartsWith("LT:"))
{
return LocalizedTextTable.GetLocalizedTextDirect(attributes[0].Description.Replace("LT:", ""));
}
else
return attributes[0].Description;
}
/// <summary>
/// Gets the description for certaing named value in an Enumeration
/// </summary>
/// <param name="value">The type of the Enumeration</param>
/// <param name="name">The name of the Enumeration value</param>
/// <returns>The description, if any, else the passed name</returns>
public static string GetEnumDescription(System.Type value, string name)
{
FieldInfo fi = value.GetField(name);
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute), false);
if (!(attributes.Length > 0))
return name;
if (attributes[0].Description.StartsWith("LT:"))
{
return LocalizedTextTable.GetLocalizedTextDirect(attributes[0].Description.Replace("LT:", ""));
}
else
return attributes[0].Description;
//return (attributes.Length>0)?attributes[0].Description:name;
}
/// <summary>
/// Gets the value of an Enum, based on it's Description Attribute or named value
/// </summary>
/// <param name="value">The Enum type</param>
/// <param name="description">The description or name of the element</param>
/// <returns>The value, or the passed in description, if it was not found</returns>
public static object GetEnumValue(System.Type value, string description)
{
FieldInfo[] fis = value.GetFields();
foreach (FieldInfo fi in fis)
{
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
//Localized?
if (attributes[0].Description.StartsWith("LT:"))
{
//see if decoded string equals passed in string
if (LocalizedTextTable.GetLocalizedTextDirect(attributes[0].Description.Replace("LT:", "")) == description)
{
return fi.GetValue(fi.Name);
}
}
else
{//Not localized...
if (attributes[0].Description == description)
{
return fi.GetValue(fi.Name);
}
}
}
if (fi.Name == description)
{
return fi.GetValue(fi.Name);
}
}
return description;
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
public EnumDescConverter(System.Type type)
: base(type)
{
myVal = type;
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <param name="culture"></param>
/// <param name="value"></param>
/// <param name="destinationType"></param>
/// <returns></returns>
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (value is Enum && destinationType == typeof(string))
{
return GetEnumDescription((Enum)value);
}
if (value is string && destinationType == typeof(string))
{
return GetEnumDescription(myVal, (string)value);
}
return base.ConvertTo(context, culture, value, destinationType);
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <param name="culture"></param>
/// <param name="value"></param>
/// <returns></returns>
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value is string)
{
return GetEnumValue(myVal, (string)value);
}
if (value is Enum)
{
return GetEnumDescription((Enum)value);
}
return base.ConvertFrom(context, culture, value);
}
}
#endregion
}