Files
Common-VS2019/SacsStandardBase/Base/Core/DataValue.cs
T

501 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 (SacsSystem.DebugMode) SaLogger.Debug($"{SysUtil.Fn} Incorrect data type: {dataType.ToString()}.");
return false;
}
public TriStateType AsTriState ()
{
if (dataType == DataType.TriState) return (TriStateType)value;
if (dataType == DataType.Unknown) return TriStateType.Unknown;
if (SacsSystem.DebugMode) SaLogger.Debug($"{SysUtil.Fn} 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($"{SysUtil.Fn} 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($"{SysUtil.Fn} Data type: {dataType.ToString()}.");
return (double)(decimal)value;
}
if (SacsSystem.DebugMode) SaLogger.Debug($"{SysUtil.Fn} 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($"{SysUtil.Fn} 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($"{SysUtil.Fn} 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($"{SysUtil.Fn} 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($"{SysUtil.Fn} 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($"{SysUtil.Fn} 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($"{SysUtil.Fn} 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;
}
//-------------------------------------------------------------------
}
//=======================================================================
}