5270 lines
203 KiB
C#
5270 lines
203 KiB
C#
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")<(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)<(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("&", "&");
|
||
|
||
//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("&", "&");
|
||
//output = output.Replace("'", "'");
|
||
//output = output.Replace("\"", """);
|
||
//output = output.Replace(">", ">");
|
||
//output = output.Replace("<", "<");
|
||
|
||
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
|
||
|
||
|
||
|
||
}
|