569 lines
23 KiB
C#
569 lines
23 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Nini.Config;
|
|
using SafeMobileLib;
|
|
|
|
namespace MotoRepeater
|
|
{
|
|
public class Config
|
|
{
|
|
private static IConfigSource source = null;
|
|
private static string CFG_FILE_SD = "configSD.ini";
|
|
private static string CFG_FILE_SN = "configSN.ini";
|
|
|
|
// UPDATE
|
|
public bool autoupdate = true;
|
|
public bool isDevelope = false;
|
|
|
|
// APP SERVER
|
|
public string APPLICATION_SERVER_IP;
|
|
|
|
// GATEWAY
|
|
public Int64 GWCODE = 0; // manually inserted
|
|
public Int64 GWID = 0;
|
|
public Int64 PEER_ID { get; set; }
|
|
public Int32 PEER_PORT { get; set; }
|
|
|
|
// CREDENTIALS - SN
|
|
public string USERNAME { get; set; }
|
|
public string PASSWORD { get; set; }
|
|
public Boolean SIGNEDIN { get; set; }
|
|
|
|
|
|
// MESSAGE BUS - SD
|
|
public string MBUS_IP;
|
|
public int MBUS_PORT;
|
|
public Int32 MBUS_REG_PORT = 5680;
|
|
|
|
// MYSQL
|
|
public string DB_SERVER;
|
|
public string DB_DATABASE;
|
|
public string DB_USERNAME;
|
|
public string DB_PASSWORD;
|
|
public string DB_PORT;
|
|
|
|
// Loaded from the Database
|
|
|
|
// DDMS
|
|
public string DDMS_IP { get; set; }
|
|
public Int32 DDMS_PORT { get; set; }
|
|
public Int32 GPS_PORT { get; set; }
|
|
public Int32 SMS_PORT { get; set; }
|
|
public Int32 ARS_PORT { get; set; }
|
|
public Int32 TELEMETRY_PORT { get; set; }
|
|
public Int32 TALLYSMAN_PORT { get; set; }
|
|
|
|
// REGISTRATION
|
|
public Boolean SLOT1_DATA;
|
|
public Boolean SLOT2_DATA;
|
|
public Boolean SLOT1_VOICE;
|
|
public Boolean SLOT2_VOICE;
|
|
|
|
|
|
// REPEATER
|
|
public string MASTER_IP { get; set; }
|
|
public Int32 MASTER_PORT { get; set; }
|
|
public MotoRepeater.LinkEstablishment.SystemType SYSTEM_TYPE { get; set; }
|
|
public string AUTHENTICATION_KEY { get; set; }
|
|
|
|
public bool SEND_LOCATION_STOP{ get; set; }
|
|
|
|
// MISC
|
|
public Boolean AUTOUPDATE { get; set; }
|
|
|
|
|
|
|
|
private Dictionary<ConfigHeader, List<ConfigValues>> configStructureSN = new Dictionary<ConfigHeader, List<ConfigValues>>()
|
|
{
|
|
{ConfigHeader.GATEWAY, new List<ConfigValues>() {ConfigValues.CODE, ConfigValues.DATA, ConfigValues.VOICE, ConfigValues.SEND_LOCATION_STOP }},
|
|
{ConfigHeader.MYSQL, new List<ConfigValues>() {ConfigValues.SERVER, ConfigValues.DATABASE, ConfigValues.UID, ConfigValues.PASSWORD}},
|
|
{ConfigHeader.CREDENTIALS, new List<ConfigValues>() {ConfigValues.USER, ConfigValues.PWD, ConfigValues.SIGNEDIN,
|
|
ConfigValues.AUTOUPDATE}}
|
|
};
|
|
|
|
|
|
/// <summary>
|
|
/// public constructor
|
|
/// </summary>
|
|
public Config()
|
|
{
|
|
PEER_ID = 97531;
|
|
PEER_PORT = 50013;
|
|
|
|
DDMS_IP = "127.0.0.1";
|
|
DDMS_PORT = 3000;
|
|
GPS_PORT = 4001;
|
|
ARS_PORT = 4005;
|
|
SMS_PORT = 4007;
|
|
TELEMETRY_PORT = 4008;
|
|
TALLYSMAN_PORT = 4010;
|
|
|
|
SLOT1_DATA = true;
|
|
SLOT1_VOICE = false;
|
|
SLOT2_DATA = true;
|
|
SLOT2_VOICE = false;
|
|
|
|
MASTER_IP = "10.120.1.196";
|
|
MASTER_PORT = 40000;
|
|
SYSTEM_TYPE = LinkEstablishment.SystemType.IP_SITE_CONNECT;
|
|
|
|
AUTOUPDATE = false;
|
|
SEND_LOCATION_STOP = false;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Load the database settings and gateway id from the config file.
|
|
/// This function will populate the fields with the stored values
|
|
/// </summary>
|
|
public void LoadConfig(AppType type)
|
|
{
|
|
if (type == AppType.SAFENET)
|
|
{
|
|
string CFG_FILE = (type == AppType.SAFEDISPATCH ? CFG_FILE_SD : CFG_FILE_SN);
|
|
|
|
if (!File.Exists(CFG_FILE))
|
|
{
|
|
Utils.WriteLine("Config file didn't exist. Creating it...", ConsoleColor.Yellow);
|
|
try
|
|
{
|
|
using (FileStream fs = File.Create(CFG_FILE)) { }
|
|
}
|
|
catch (Exception)
|
|
{
|
|
Utils.WriteLine("Application ended!!!! " + CFG_FILE + " could not be created");
|
|
Console.WriteLine("Press any key to exit...");
|
|
Console.ReadKey();
|
|
System.Environment.Exit(0);
|
|
}
|
|
}
|
|
|
|
FileInfo configFile = new FileInfo(CFG_FILE);
|
|
|
|
|
|
try
|
|
{
|
|
// here the config file must exist
|
|
source = new IniConfigSource(CFG_FILE);
|
|
source.AutoSave = true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Utils.WriteLine("Config File was not in the correct format![1] " + ex.ToString(), ConsoleColor.Red);
|
|
try
|
|
{
|
|
// copy config file to a back-up one
|
|
File.Copy(CFG_FILE, "config.ini_" + String.Format("{0:dd.MMM_HH.mm.ss}", DateTime.Now) + ".bak");
|
|
|
|
// delete config file
|
|
File.Delete(CFG_FILE);
|
|
// recreate file
|
|
using (FileStream fs = File.Create(CFG_FILE)) { }
|
|
|
|
if (OnConfigFileWasBroken != null)
|
|
OnConfigFileWasBroken();
|
|
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
Utils.WriteLine("He's dead, Jim! " + ex2.ToString(), ConsoleColor.Red);
|
|
Console.WriteLine("Press any key to exit...");
|
|
Console.ReadKey();
|
|
System.Environment.Exit(0);
|
|
}
|
|
}
|
|
|
|
|
|
try
|
|
{
|
|
// here the config file must exist
|
|
source = new IniConfigSource(CFG_FILE);
|
|
source.AutoSave = true;
|
|
|
|
foreach (KeyValuePair<ConfigHeader, List<ConfigValues>> pair in configStructureSN)
|
|
{
|
|
try
|
|
{
|
|
// check if the header exists
|
|
if (source.Configs[pair.Key.ToString()] == null)
|
|
{
|
|
source.AddConfig(pair.Key.ToString());
|
|
|
|
foreach (ConfigValues cfg in pair.Value)
|
|
source.Configs[pair.Key.ToString()].Set(cfg.ToString(), cfg.GetDefaultValue());
|
|
}
|
|
else
|
|
{
|
|
foreach (ConfigValues cfg in pair.Value)
|
|
{
|
|
if (source.Configs[pair.Key.ToString()].Get(cfg.ToString()) == null)
|
|
source.Configs[pair.Key.ToString()].Set(cfg.ToString(), cfg.GetDefaultValue());
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Utils.WriteLine("Could not write Config Header or value [" + pair.Key.ToString() + " ] " + ex.ToString(), ConsoleColor.Red);
|
|
Console.WriteLine("Press any key to exit...");
|
|
Console.ReadKey();
|
|
System.Environment.Exit(0);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Utils.WriteLine("Config File was not in the correct format[2] " + ex.ToString(), ConsoleColor.Red);
|
|
Console.WriteLine("Press any key to exit...");
|
|
Console.ReadKey();
|
|
System.Environment.Exit(0);
|
|
}
|
|
}
|
|
|
|
switch(type)
|
|
{
|
|
case AppType.SAFENET:
|
|
{
|
|
try
|
|
{
|
|
source = new IniConfigSource(CFG_FILE_SN);
|
|
GWCODE = Convert.ToInt64(source.Configs["GATEWAY"].Get("CODE"));
|
|
|
|
//MySQL connection
|
|
DB_SERVER = TESEncryption.Decrypt(source.Configs["MySQL"].Get("SERVER"));
|
|
DB_DATABASE = TESEncryption.Decrypt(source.Configs["MySQL"].Get("DATABASE"));
|
|
DB_USERNAME = TESEncryption.Decrypt(source.Configs["MySQL"].Get("UID"));
|
|
DB_PASSWORD = TESEncryption.Decrypt(source.Configs["MySQL"].Get("PASSWORD"));
|
|
|
|
SLOT1_DATA = Convert.ToBoolean(source.Configs["GATEWAY"].Get("data"));
|
|
SLOT2_DATA = Convert.ToBoolean(source.Configs["GATEWAY"].Get("data"));
|
|
SLOT1_VOICE = Convert.ToBoolean(source.Configs["GATEWAY"].Get("voice"));
|
|
SLOT2_VOICE = Convert.ToBoolean(source.Configs["GATEWAY"].Get("voice"));
|
|
|
|
if (!source.Configs["GATEWAY"].Contains("send_location_stop"))
|
|
{
|
|
source.Configs["GATEWAY"].Set("send_location_stop", "false");
|
|
source.Save();
|
|
}
|
|
|
|
SEND_LOCATION_STOP = Convert.ToBoolean(source.Configs["GATEWAY"].Get("send_location_stop"));
|
|
|
|
USERNAME = source.Configs["CREDENTIALS"].Get("USER");
|
|
PASSWORD = source.Configs["CREDENTIALS"].Get("PASSWORD").Length > 0 ? TESEncryption.Decrypt(source.Configs["CREDENTIALS"].Get("PASSWORD")) : "";
|
|
SIGNEDIN = Convert.ToBoolean(source.Configs["CREDENTIALS"].Get("SIGNEDIN"));
|
|
AUTOUPDATE = Convert.ToBoolean(source.Configs["CREDENTIALS"].Get("AUTOUPDATE"));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Utils.WriteLine("Loading Config File Error : " + ex.Message.ToString(), ConsoleColor.DarkRed);
|
|
}
|
|
break;
|
|
}
|
|
case AppType.SAFEDISPATCH:
|
|
{
|
|
try
|
|
{
|
|
source = new IniConfigSource(CFG_FILE_SD);
|
|
GWID = Convert.ToInt32(source.Configs[ "GATEWAY"].Get("id"));
|
|
MBUS_REG_PORT = Convert.ToInt32(source.Configs["GATEWAY"].Get("regPort"));
|
|
|
|
DDMS_IP = source.Configs["GATEWAY"].Get("ddmsip");
|
|
DDMS_PORT = Convert.ToInt32(source.Configs["GATEWAY"].Get("ddms_port"));
|
|
GPS_PORT = Convert.ToInt32(source.Configs["GATEWAY"].Get("gps_port"));
|
|
SMS_PORT = Convert.ToInt32(source.Configs["GATEWAY"].Get("tm_port"));
|
|
TELEMETRY_PORT = Convert.ToInt32(source.Configs["GATEWAY"].Get("telem_port"));
|
|
TALLYSMAN_PORT = Convert.ToInt32(source.Configs["GATEWAY"].Get("tallysman_port"));
|
|
SLOT1_DATA = Convert.ToBoolean(source.Configs["GATEWAY"].Get("data"));
|
|
SLOT2_DATA = Convert.ToBoolean(source.Configs["GATEWAY"].Get("data"));
|
|
SLOT1_VOICE = Convert.ToBoolean(source.Configs["GATEWAY"].Get("voice"));
|
|
SLOT2_VOICE = Convert.ToBoolean(source.Configs["GATEWAY"].Get("voice"));
|
|
|
|
if (!source.Configs["GATEWAY"].Contains("send_location_stop"))
|
|
{
|
|
source.Configs["GATEWAY"].Set("send_location_stop", "false");
|
|
source.Save();
|
|
}
|
|
|
|
SEND_LOCATION_STOP = Convert.ToBoolean(source.Configs["GATEWAY"].Get("send_location_stop"));
|
|
|
|
if (source.Configs["Server"] == null)
|
|
{
|
|
source.Configs.Add("Server");
|
|
source.Save();
|
|
}
|
|
|
|
if (!source.Configs["Server"].Contains("IP"))
|
|
{
|
|
source.Configs["Server"].Set("IP", "127.0.0.1");
|
|
source.Save();
|
|
}
|
|
|
|
APPLICATION_SERVER_IP = source.Configs["Server"].GetString("IP");
|
|
|
|
|
|
/*
|
|
DB_SERVER = source.Configs["Database"].Get("IP");
|
|
DB_DATABASE = source.Configs["Database"].Get("Schema");
|
|
DB_USERNAME = source.Configs["Database"].Get("User");
|
|
DB_PASSWORD = source.Configs["Database"].Get("Passwd");
|
|
DB_PORT = source.Configs["Database"].Get("Port");
|
|
|
|
MBUS_IP = source.Configs["MESSAGEBUS"].Get("ip");
|
|
MBUS_PORT = Convert.ToInt32(source.Configs["MESSAGEBUS"].Get("port"));
|
|
*/
|
|
// NAI values
|
|
PEER_ID = Convert.ToInt64(source.Configs["NAI"].Get("peerID"));
|
|
PEER_PORT = Convert.ToInt32(source.Configs["NAI"].Get("peerPort"));
|
|
MASTER_IP = source.Configs["NAI"].Get("masterRepeaterIP");
|
|
MASTER_PORT = Convert.ToInt32(source.Configs["NAI"].Get("masterRepeaterPort"));
|
|
AUTHENTICATION_KEY = source.Configs["NAI"].Get("authenticationKey");
|
|
SYSTEM_TYPE = GetSystemTypeObjFromConfig(source.Configs["NAI"].Get("networkType"));
|
|
|
|
|
|
try
|
|
{
|
|
if (!source.Configs["UPDATE"].Contains("autoupdate")) {
|
|
source.Configs["UPDATE"].Set("autoupdate", true);
|
|
source.Save();
|
|
}
|
|
|
|
autoupdate = source.Configs["UPDATE"].GetBoolean("autoupdate");
|
|
|
|
if (source.Configs["UPDATE"].Contains("develop")) {
|
|
isDevelope = source.Configs["UPDATE"].GetBoolean("develop");
|
|
source.Save();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Utils.WriteLine("AUTOUPDATE " + ex.ToString(), ConsoleColor.Red);
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Utils.WriteLine("Loading Config File Error : " + ex.Message.ToString(), ConsoleColor.DarkRed);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public void SaveConfigOption(String header, String property, String value)
|
|
{
|
|
try
|
|
{
|
|
source = new IniConfigSource(CFG_FILE_SD);
|
|
|
|
//DataBase
|
|
source.Configs[header].Set(property, value);
|
|
|
|
// Save the INI file
|
|
source.Save();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Utils.WriteLine(ex.ToString(), ConsoleColor.Red);
|
|
}
|
|
Utils.WriteLine("SaveConfigOption OK");
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Update all the values from the config file based on the values received from the DataBase
|
|
/// </summary>
|
|
/// <param name="config">Repeater Configuration parameters</param>
|
|
public void UpdateRepeaterConfig(RepeaterConfig config)
|
|
{
|
|
ARS_PORT = config.ARSPort;
|
|
AUTHENTICATION_KEY = config.AuthenticationKey;
|
|
DDMS_IP = config.DDMSIP;
|
|
DDMS_PORT = config.DDMSPort;
|
|
GWID = config.GatewayID;
|
|
GWCODE = config.GatewayCode;
|
|
GPS_PORT = config.LocationPort;
|
|
PEER_ID = config.PeerID;
|
|
MASTER_IP = config.RepeaterIP;
|
|
MASTER_PORT = config.RepeaterPort;
|
|
/*
|
|
SLOT1_DATA = true;
|
|
SLOT1_VOICE = true;
|
|
SLOT2_DATA = true;
|
|
SLOT2_VOICE = true;
|
|
*/
|
|
SYSTEM_TYPE = GetSystemTypeObjFromConfig(config.SystemType);
|
|
TELEMETRY_PORT = config.TelemetryPort;
|
|
TALLYSMAN_PORT = config.TallysmanPort;
|
|
SMS_PORT = config.TextPort;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Update a specific config file parameter from a desired category.
|
|
/// </summary>
|
|
/// <param name="category">Category in which the parameter is located</param>
|
|
/// <param name="option">Parameter which needs to be updated</param>
|
|
/// <param name="value">New value for the desired parameter</param>
|
|
public static void UpdateConfigParameter(string category, string option, string value)
|
|
{
|
|
try
|
|
{
|
|
source = new IniConfigSource(MotoRepeater_GW.appType == AppType.SAFEDISPATCH ? CFG_FILE_SD : CFG_FILE_SN);
|
|
//DataBase
|
|
source.Configs[category].Set(option, value);
|
|
// Save the INI file
|
|
source.Save();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Utils.WriteLine("Update Config Parameters: " + ex.ToString(), ConsoleColor.Red);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Get the system type as a string value based on the system type as a string.
|
|
/// This value will be used to be written in the config file
|
|
/// </summary>
|
|
/// <param name="systemType">System type as a string representation</param>
|
|
/// <returns>A string which needs to written in the config file</returns>
|
|
public static string GetSystemTypeForConfig(string systemType)
|
|
{
|
|
switch (systemType)
|
|
{
|
|
case "Single/IP Site Connect": return GetSystemTypeForConfig(LinkEstablishment.SystemType.IP_SITE_CONNECT);
|
|
case "Capacity Plus": return GetSystemTypeForConfig(LinkEstablishment.SystemType.CAPACITY_PLUS);
|
|
default: return GetSystemTypeForConfig(LinkEstablishment.SystemType.LINKED_CAPACITY_PLUS);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the system type as a string value based on the SystemType enum
|
|
/// This value will be used to be written in the config file
|
|
/// </summary>
|
|
/// <param name="systemType">SystemType object with the type of the system</param>
|
|
/// <returns>A string which needs to written in the config file</returns>
|
|
public static string GetSystemTypeForConfig(LinkEstablishment.SystemType systemType)
|
|
{
|
|
switch (systemType)
|
|
{
|
|
case LinkEstablishment.SystemType.CAPACITY_PLUS: return "CPP";
|
|
case LinkEstablishment.SystemType.IP_SITE_CONNECT: return "IPSC";
|
|
default: return "LCP";
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Get the system type as a human readable value based on the value from config file
|
|
/// </summary>
|
|
/// <param name="systemType">String with the system type read from the config file</param>
|
|
/// <returns>Human readable system type value</returns>
|
|
public static string GetSystemTypeFromConfig(string systemType)
|
|
{
|
|
switch (systemType)
|
|
{
|
|
case "CPP": return "Capacity Plus";
|
|
case "IPSC": return "Single/IP Site Connect";
|
|
case "LCP": return "Linked Capacity Plus";
|
|
default: return "Linked Capacity Plus";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the system type as a SystemType object value based on the value from config file
|
|
/// </summary>
|
|
/// <param name="systemType">String with the system type read from the config file</param>
|
|
/// <returns>SystemType object value</returns>
|
|
public static LinkEstablishment.SystemType GetSystemTypeObjFromConfig(string systemType)
|
|
{
|
|
switch (systemType)
|
|
{
|
|
case "CPP": return LinkEstablishment.SystemType.CAPACITY_PLUS;
|
|
case "IPSC": return LinkEstablishment.SystemType.IP_SITE_CONNECT;
|
|
case "LCP": return LinkEstablishment.SystemType.LINKED_CAPACITY_PLUS;
|
|
default: return LinkEstablishment.SystemType.LINKED_CAPACITY_PLUS;
|
|
}
|
|
}
|
|
|
|
|
|
public delegate void ConfigFileWasBroken();
|
|
public event ConfigFileWasBroken OnConfigFileWasBroken;
|
|
}
|
|
|
|
|
|
|
|
#region CONFIG STRING ENUMS
|
|
public sealed class ConfigHeader
|
|
{
|
|
|
|
private readonly String name;
|
|
private readonly int value;
|
|
|
|
public static readonly ConfigHeader CREDENTIALS = new ConfigHeader(1, "CREDENTIALS");
|
|
public static readonly ConfigHeader GATEWAY = new ConfigHeader(2, "GATEWAY");
|
|
public static readonly ConfigHeader MYSQL = new ConfigHeader(3, "MySQL");
|
|
|
|
private ConfigHeader(int value, String name)
|
|
{
|
|
this.name = name;
|
|
this.value = value;
|
|
}
|
|
|
|
public override String ToString()
|
|
{
|
|
return name;
|
|
}
|
|
}
|
|
|
|
public sealed class ConfigValues
|
|
{
|
|
|
|
private readonly String name;
|
|
private readonly String defaultValue;
|
|
private readonly int value;
|
|
|
|
public static readonly ConfigValues USER = new ConfigValues(11, "USER", "");
|
|
public static readonly ConfigValues PWD = new ConfigValues(12, "PASSWORD", "");
|
|
public static readonly ConfigValues SIGNEDIN = new ConfigValues(13, "SIGNEDIN", "false");
|
|
public static readonly ConfigValues AUTOUPDATE = new ConfigValues(14, "AUTOUPDATE", "true");
|
|
|
|
public static readonly ConfigValues CODE = new ConfigValues(21, "CODE", "90999");
|
|
public static readonly ConfigValues DATA = new ConfigValues(22, "data", "true");
|
|
public static readonly ConfigValues VOICE = new ConfigValues(23, "voice", "false");
|
|
public static readonly ConfigValues SEND_LOCATION_STOP = new ConfigValues(24, "send_location_stop", "false");
|
|
|
|
|
|
public static readonly ConfigValues SERVER = new ConfigValues(31, "SERVER", //"440j5IlHnEcbFgsQToeQmg==");
|
|
"ifqNConpwMO2SAGta2monK+/fXuIK0gG+yH/By/fKWTTSHvNzVOJB6WKfOLHGcA1R9csQWwX4kU=");
|
|
public static readonly ConfigValues DATABASE = new ConfigValues(32, "DATABASE", "9F5Ufu/mgM9Btd7HWDylwg==");
|
|
public static readonly ConfigValues UID = new ConfigValues(33, "UID", "5wQPPYB9Xwg=");
|
|
public static readonly ConfigValues PASSWORD = new ConfigValues(34, "PASSWORD", "YTXqw1P9AMJH1yxBbBfiRQ==");
|
|
|
|
|
|
private ConfigValues(int value, String name, String defaultValue)
|
|
{
|
|
this.name = name;
|
|
this.value = value;
|
|
this.defaultValue = defaultValue;
|
|
}
|
|
|
|
public override String ToString()
|
|
{
|
|
return name;
|
|
}
|
|
|
|
public String GetDefaultValue()
|
|
{
|
|
return defaultValue;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|