503 lines
15 KiB
C#
503 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Sarand.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.Utils;
|
|
|
|
namespace Sarand.Net.Standard.Base.Core
|
|
{
|
|
//=======================================================================
|
|
public class DataValue
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Definitions.
|
|
public enum DataType { Unknown = 0, Bool, TriState, Long, Double, Decimal, String, Date, Time, DateTime, Blob };
|
|
public enum TriStateType { Unknown = 0, Red, Amber, Green, Blue, Purple, Yellow };
|
|
|
|
//-------------------------------------------------------------------
|
|
// Data members.
|
|
private DataType dataType;
|
|
private Object value;
|
|
|
|
//-------------------------------------------------------------------
|
|
// Construction.
|
|
public DataValue () { }
|
|
public DataValue (DataValue dataValue)
|
|
{
|
|
if (dataValue != null)
|
|
{
|
|
dataType = dataValue.GetDataType();
|
|
value = dataValue.value;
|
|
}
|
|
}
|
|
public DataValue (bool value)
|
|
{
|
|
this.value = value;
|
|
this.dataType = DataType.Bool;
|
|
}
|
|
public DataValue (TriStateType value)
|
|
{
|
|
this.value = value;
|
|
this.dataType = DataType.TriState;
|
|
}
|
|
public DataValue (long value)
|
|
{
|
|
this.value = value;
|
|
this.dataType = DataType.Long;
|
|
}
|
|
public DataValue (double value)
|
|
{
|
|
this.value = value;
|
|
this.dataType = DataType.Double;
|
|
}
|
|
public DataValue (decimal value)
|
|
{
|
|
this.value = value;
|
|
this.dataType = DataType.Decimal;
|
|
}
|
|
public DataValue (String value)
|
|
{
|
|
this.value = value;
|
|
this.dataType = DataType.String;
|
|
}
|
|
public DataValue (DateTime value, DataType type = DataType.DateTime)
|
|
{
|
|
this.value = value;
|
|
switch (type)
|
|
{
|
|
case DataType.Date:
|
|
case DataType.Time:
|
|
case DataType.DateTime:
|
|
this.dataType = type;
|
|
break;
|
|
default:
|
|
this.dataType = DataType.DateTime;
|
|
break;
|
|
}
|
|
}
|
|
public DataValue (Byte[] value)
|
|
{
|
|
this.value = value;
|
|
this.dataType = DataType.Blob;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Properties.
|
|
public static readonly DataValue NullValue = new DataValue();
|
|
public DataType GetDataType ()
|
|
{
|
|
return dataType;
|
|
}
|
|
public static String GetTypeDesc (DataType type)
|
|
{
|
|
// Converts type to string.
|
|
switch (type)
|
|
{
|
|
case DataType.Bool: return "Bool";
|
|
case DataType.TriState: return "TriState";
|
|
case DataType.Long: return "Long";
|
|
case DataType.Double: return "Double";
|
|
case DataType.Decimal: return "Decimal";
|
|
case DataType.String: return "String";
|
|
case DataType.Date: return "Date";
|
|
case DataType.Time: return "Time";
|
|
case DataType.DateTime: return "DateTime";
|
|
case DataType.Blob: return "Blob";
|
|
}
|
|
return "<Unknown>";
|
|
}
|
|
public String GetTypeDesc ()
|
|
{
|
|
return GetTypeDesc(dataType);
|
|
}
|
|
public bool IsValid ()
|
|
{
|
|
return (dataType != DataType.Unknown);
|
|
}
|
|
public bool IsNumeric ()
|
|
{
|
|
return (dataType == DataType.Long || dataType == DataType.Double || dataType == DataType.Decimal);
|
|
}
|
|
public bool IsDate ()
|
|
{
|
|
return (dataType == DataType.Date || dataType == DataType.DateTime);
|
|
}
|
|
public bool IsTime ()
|
|
{
|
|
return (dataType == DataType.Time || dataType == DataType.DateTime);
|
|
}
|
|
public bool IsDateTime ()
|
|
{
|
|
return (dataType == DataType.Date || dataType == DataType.Time || dataType == DataType.DateTime);
|
|
}
|
|
public bool IsBlob ()
|
|
{
|
|
return (dataType == DataType.Blob);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Conversion.
|
|
public override String ToString ()
|
|
{
|
|
if (value == null) return String.Empty;
|
|
// Forces any data type to string.
|
|
switch (dataType)
|
|
{
|
|
case DataType.Bool: return ((bool)value ? "Y" : "N");
|
|
case DataType.TriState: return ((TriStateType)value).ToString();
|
|
case DataType.Long: return ((long)value).ToString();
|
|
case DataType.Double: return ((double)value).ToString();
|
|
case DataType.Decimal: return ((decimal)value).ToString();
|
|
case DataType.String: return (String)value;
|
|
case DataType.Date: return ((DateTime)value).ToString("yyyyMMdd");
|
|
case DataType.Time: return ((DateTime)value).ToString("HH:mm:ss");
|
|
case DataType.DateTime: return ((DateTime)value).ToString("yyyyMMddHHmmss");
|
|
}
|
|
return String.Empty;
|
|
}
|
|
public double ToNumeric ()
|
|
{
|
|
if (value == null) return 0.0;
|
|
// Convert any type to double numeric.
|
|
switch (dataType)
|
|
{
|
|
case DataType.Bool: return ((bool)value ? 1 : 0);
|
|
case DataType.TriState: return (int)(TriStateType)value;
|
|
case DataType.Long: return (long)value;
|
|
case DataType.Double: return (double)value;
|
|
case DataType.Decimal: return (double)(decimal)value;
|
|
case DataType.String: return StringUtil.ToDouble((String)value);
|
|
case DataType.Date: return ((DateTime)value).Ticks;
|
|
case DataType.Time: return ((DateTime)value).Ticks;
|
|
case DataType.DateTime: return ((DateTime)value).Ticks;
|
|
}
|
|
return 0.0;
|
|
}
|
|
/// <summary>Return value interpretted as boolean.</summary>
|
|
public bool ToBool ()
|
|
{
|
|
if (value == null) return false;
|
|
// Numeric <> 0, String: 'Yes', 'True', numeric value.
|
|
switch (dataType)
|
|
{
|
|
case DataType.Bool: return (bool)value;
|
|
case DataType.TriState: return (TriStateType)value != TriStateType.Unknown;
|
|
case DataType.Long: return (long)value != 0;
|
|
case DataType.Double: return (double)value != 0.0;
|
|
case DataType.Decimal: return (decimal)value != 0.0m;
|
|
case DataType.String: return ((String)value).ToBool();
|
|
case DataType.Date: return ((DateTime)value).Ticks != 0;
|
|
case DataType.Time: return ((DateTime)value).Ticks != 0;
|
|
case DataType.DateTime: return ((DateTime)value).Ticks != 0;
|
|
}
|
|
return false;
|
|
}
|
|
/// <summary>Return explicit boolean value or false for other types.</summary>
|
|
public bool AsBool ()
|
|
{
|
|
// Convert to specific type of data - fails if type is not correct:
|
|
if (dataType == DataType.Bool) return (bool)value;
|
|
if (dataType == DataType.Unknown) return false;
|
|
#if DEBUG
|
|
SaLogger.Debug(GetType().Name + ".AsBool Incorrect data type: " + dataType.ToString());
|
|
#endif
|
|
return false;
|
|
}
|
|
public TriStateType AsTriState ()
|
|
{
|
|
if (dataType == DataType.TriState) return (TriStateType)value;
|
|
if (dataType == DataType.Unknown) return TriStateType.Unknown;
|
|
if (SacsSystem.DebugMode) SaLogger.Debug(GetType().Name + ".AsTriState Incorrect data type: " + dataType.ToString());
|
|
return TriStateType.Unknown;
|
|
}
|
|
public long AsLong ()
|
|
{
|
|
if (dataType == DataType.Long) return (long)value;
|
|
if (dataType == DataType.Unknown) return 0;
|
|
if (SacsSystem.DebugMode) SaLogger.Debug(GetType().Name + ".AsLong Incorrect data type: " + dataType.ToString());
|
|
return 0;
|
|
}
|
|
public double AsDouble ()
|
|
{
|
|
if (dataType == DataType.Double) return (double)value;
|
|
if (dataType == DataType.Unknown) return 0.0;
|
|
// Aug-2018 Temporarily allow decimal values to be returned as double.
|
|
if (dataType == DataType.Decimal)
|
|
{
|
|
SaLogger.Warn(GetType().Name + ".AsDouble Data type: " + dataType.ToString());
|
|
return (double)(decimal)value;
|
|
}
|
|
if (SacsSystem.DebugMode) SaLogger.Debug(GetType().Name + ".AsDouble Incorrect data type: " + dataType.ToString());
|
|
return 0.0;
|
|
}
|
|
public decimal AsDecimal ()
|
|
{
|
|
if (dataType == DataType.Decimal) return (decimal)value;
|
|
if (dataType == DataType.Unknown) return 0.00m;
|
|
if (SacsSystem.DebugMode) SaLogger.Debug(GetType().Name + ".AsDecimal Incorrect data type: " + dataType.ToString());
|
|
return 0.00m;
|
|
}
|
|
public String AsString ()
|
|
{
|
|
if (dataType == DataType.String) return (String)value;
|
|
if (dataType == DataType.Unknown) return "";
|
|
if (SacsSystem.DebugMode) SaLogger.Debug(GetType().Name + ".AsString Incorrect data type: " + dataType.ToString());
|
|
return "";
|
|
}
|
|
public DateTime AsDateTime ()
|
|
{
|
|
// NB DateTime.Ticks is NotFiniteNumberException of 100-nanosecond intervals since beginning of 1st January 0001.
|
|
if (dataType == DataType.Date || dataType == DataType.Time || dataType == DataType.DateTime) return (DateTime)value;
|
|
if (dataType == DataType.Unknown) return DateTime.MinValue;
|
|
if (SacsSystem.DebugMode) SaLogger.Debug(GetType().Name + ".AsDateTime Incorrect data type: " + dataType.ToString());
|
|
return DateTime.MinValue;
|
|
}
|
|
public DateTime AsDate ()
|
|
{
|
|
if (dataType == DataType.Date || dataType == DataType.DateTime) return ((DateTime)value).Date;
|
|
if (dataType == DataType.Unknown) return DateTime.MinValue;
|
|
if (SacsSystem.DebugMode) SaLogger.Debug(GetType().Name + ".AsDate Incorrect data type: " + dataType.ToString());
|
|
return DateTime.MinValue;
|
|
}
|
|
public DateTime AsTime ()
|
|
{
|
|
if (dataType == DataType.Time || dataType == DataType.DateTime) return (DateTime)value;
|
|
if (dataType == DataType.Unknown) return DateTime.MinValue;
|
|
if (SacsSystem.DebugMode) SaLogger.Debug(GetType().Name + ".AsTime Incorrect data type: " + dataType.ToString());
|
|
return DateTime.MinValue;
|
|
}
|
|
public Byte[] AsBlob ()
|
|
{
|
|
if (dataType == DataType.Blob) return (Byte[])value;
|
|
if (dataType == DataType.Unknown) return null;
|
|
if (SacsSystem.DebugMode) SaLogger.Debug(GetType().Name + ".AsBlob Incorrect data type: " + dataType.ToString());
|
|
return null;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Comparison.
|
|
public bool Equals (DataValue value)
|
|
{
|
|
return false;
|
|
}
|
|
public int CompareTo (DataValue value)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Utilities.
|
|
public void Clear ()
|
|
{
|
|
dataType = DataType.Unknown;
|
|
value = null;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Arithmeic.
|
|
public void Increment (DataValue value)
|
|
{
|
|
if (dataType == value.GetDataType())
|
|
{
|
|
switch (dataType)
|
|
{
|
|
case DataType.Long:
|
|
this.value = (long)(this.value) + value.AsLong();
|
|
break;
|
|
case DataType.Double:
|
|
this.value = (double)(this.value) + value.AsDouble();
|
|
break;
|
|
case DataType.Decimal:
|
|
this.value = (decimal)(this.value) + value.AsDecimal();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
public void Decrement (DataValue value)
|
|
{
|
|
if (dataType == value.GetDataType())
|
|
{
|
|
switch (dataType)
|
|
{
|
|
case DataType.Long:
|
|
this.value = (long)(this.value) - value.AsLong();
|
|
break;
|
|
case DataType.Double:
|
|
this.value = (double)(this.value) - value.AsDouble();
|
|
break;
|
|
case DataType.Decimal:
|
|
this.value = (decimal)(this.value) - value.AsDecimal();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
public void MultiplyBy (DataValue value)
|
|
{
|
|
if (dataType == value.GetDataType())
|
|
{
|
|
switch (dataType)
|
|
{
|
|
case DataType.Long:
|
|
this.value = (long)(this.value) * value.AsLong();
|
|
break;
|
|
case DataType.Double:
|
|
this.value = (double)(this.value) * value.AsDouble();
|
|
break;
|
|
case DataType.Decimal:
|
|
this.value = (decimal)(this.value) * value.AsDecimal();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
public void DivideBy (DataValue value)
|
|
{
|
|
if (dataType == value.GetDataType())
|
|
{
|
|
switch (dataType)
|
|
{
|
|
case DataType.Long:
|
|
this.value = (long)(this.value) / value.AsLong();
|
|
break;
|
|
case DataType.Double:
|
|
this.value = (double)(this.value) / value.AsDouble();
|
|
break;
|
|
case DataType.Decimal:
|
|
this.value = (decimal)(this.value) / value.AsDecimal();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
|
|
//=======================================================================
|
|
// Data Value list extension functions.
|
|
|
|
public static class DataValueList
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Population.
|
|
|
|
/// <summary>Add a String value to the list.</summary>
|
|
public static void Add(this List<DataValue> values, String value)
|
|
{
|
|
values.Add(new DataValue(value));
|
|
}
|
|
|
|
/// <summary>Add a boolean value to the list.</summary>
|
|
public static void Add(this List<DataValue> values, bool value)
|
|
{
|
|
values.Add(new DataValue(value));
|
|
}
|
|
|
|
/// <summary>Add an integer value to the list.</summary>
|
|
public static void Add(this List<DataValue> values, int value)
|
|
{
|
|
values.Add(new DataValue(value));
|
|
}
|
|
|
|
/// <summary>Add a long value to the list.</summary>
|
|
public static void Add(this List<DataValue> values, long value)
|
|
{
|
|
values.Add(new DataValue(value));
|
|
}
|
|
|
|
/// <summary>Add a double value to the list.</summary>
|
|
public static void Add(this List<DataValue> values, double value)
|
|
{
|
|
values.Add(new DataValue(value));
|
|
}
|
|
|
|
/// <summary>Add a decimal value to the list.</summary>
|
|
public static void Add(this List<DataValue> values, decimal value)
|
|
{
|
|
values.Add(new DataValue(value));
|
|
}
|
|
|
|
/// <summary>Add a date time value to the list.</summary>
|
|
public static void Add(this List<DataValue> values, DateTime value)
|
|
{
|
|
values.Add(new DataValue(value));
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Conversion.
|
|
|
|
/// <summary>Convert all data values to strings.</summary>
|
|
public static List<String> ToStringList (this List<DataValue> values)
|
|
{
|
|
List<String> stringValues = new List<String>();
|
|
foreach (var dataValue in values)
|
|
stringValues.Add(values.ToString());
|
|
return stringValues;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert the data values to raw objects.
|
|
/// <para>eg. For population to Excel spreadsheet cells.</para>
|
|
/// </summary>
|
|
public static List<Object> ToObjectList (this List<DataValue> values)
|
|
{
|
|
List<Object> cellValues = new List<Object>();
|
|
foreach (DataValue value in values)
|
|
{
|
|
if (value.GetDataType() == DataValue.DataType.Bool)
|
|
cellValues.Add(value.AsBool());
|
|
else if (value.GetDataType() == DataValue.DataType.Long)
|
|
cellValues.Add(value.AsLong());
|
|
else if (value.GetDataType() == DataValue.DataType.Double)
|
|
cellValues.Add(value.AsDouble());
|
|
else if (value.GetDataType() == DataValue.DataType.Decimal)
|
|
cellValues.Add(value.AsDecimal());
|
|
else if (value.IsDateTime())
|
|
cellValues.Add(value.AsDateTime());
|
|
else
|
|
// Default - String value.
|
|
cellValues.Add(value.ToString());
|
|
}
|
|
return cellValues;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Numeric - only with compatible numeric values.
|
|
|
|
/// <summary>Minimum numeric value in the list.</summary>
|
|
public static DataValue GetMinValue (this List<DataValue> values)
|
|
{
|
|
DataValue minValue = null;
|
|
foreach (var dataValue in values)
|
|
{
|
|
if (dataValue.IsNumeric())
|
|
{
|
|
if (minValue == null)
|
|
minValue = new DataValue(dataValue.ToNumeric());
|
|
else if (dataValue.ToNumeric() < minValue.ToNumeric())
|
|
minValue = new DataValue(dataValue.ToNumeric());
|
|
}
|
|
}
|
|
return minValue;
|
|
}
|
|
|
|
/// <summary>Maximum numeric value in the list.</summary>
|
|
public static DataValue GetMaxValue (this List<DataValue> values)
|
|
{
|
|
DataValue maxValue = null;
|
|
foreach (var dataValue in values)
|
|
{
|
|
if (dataValue.IsNumeric())
|
|
{
|
|
if (maxValue == null)
|
|
maxValue = new DataValue(dataValue.ToNumeric());
|
|
else if (dataValue.ToNumeric() > maxValue.ToNumeric())
|
|
maxValue = new DataValue(dataValue.ToNumeric());
|
|
}
|
|
}
|
|
return maxValue;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
|
|
//=======================================================================
|
|
}
|