using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Reflection;
using System.Configuration;
using CommonData;
using Interfaces;
namespace CommonUtilities
{
public class CommonConfig : IConfig
{
#region Private members
/// <summary>
/// The _config file
/// </summary>
private string _configFile;
/// <summary>
/// The settings dictionay
/// </summary>
private readonly Dictionary<string, string> _allSettings = new Dictionary<string, string>();
#endregion
#region Constructor
/// <summary>
/// Prevents a default instance of the <see cref="CommonConfig"/> class from being created.
/// </summary>
public CommonConfig()
{
UseLocalConfig = true;
}
#endregion
#region Properties
/// <summary>
/// The current Installed application on the machine
/// </summary>
public string InstallationPath { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [use local configuration].
/// </summary>
/// <value>
/// <c>true</c> if [use local configuration]; otherwise, <c>false</c>.
/// </value>
public bool UseLocalConfig { get; set; }
/// <summary>
/// Defines the configuration file.
/// </summary>
/// <returns></returns>
private string DefineConfigFile()
{
string s = ConfigurationManager.AppSettings["LocalConfig"];
if (UseLocalConfig ||
(null != s && string.Equals(bool.TrueString, s, StringComparison.InvariantCultureIgnoreCase)))
{
Assembly asm = Assembly.GetExecutingAssembly();
string asmFileName = AssemblyHelper.AssemblyFileName(asm);
// ReSharper disable AssignNullToNotNullAttribute
string confFileName = Path.Combine(Path.GetDirectoryName(asmFileName), AppConstants.GlobalConfigFileName);
// ReSharper restore AssignNullToNotNullAttribute
if (File.Exists(confFileName))
{
return confFileName;
}
}
return Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "ST"), AppConstants.GlobalConfigFileName);
}
/// <summary>
/// The global config file path
/// </summary>
public string GlobalConfigFile
{
get
{
if (_configFile == null)
{
_configFile = DefineConfigFile();
}
return (_configFile);
}
}
#endregion
#region XML Helper methods
/// <summary>
/// Gets the XML document.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="key">The key.</param>
/// <param name="appSettingValueNode">The application setting value node.</param>
/// <returns></returns>
private XmlDocument GetXmlDoc(string fileName, string key, out XmlNode appSettingValueNode)
{
appSettingValueNode = null;
if (!File.Exists(fileName))
return null;
// create XML reader
var xmlDoc = new XmlDocument();
using (XmlReader xmlReader = new XmlTextReader(fileName))
{
// load file
xmlDoc.Load(xmlReader);
}
// parse file
//Using regex to select the Server Url and then changes the xml file accordingly
var appSettingNode = xmlDoc.SelectSingleNode("/configuration/appSettings/add[@key = '{0}']".Fmt(key));
if (appSettingNode == null || appSettingNode.Attributes == null)
return xmlDoc;
appSettingValueNode = appSettingNode.Attributes.GetNamedItem("value");
return xmlDoc;
}
/// <summary>
/// Add new element to XML file
/// </summary>
/// <param name="xmlDoc"></param>
/// <param name="elementName"></param>
/// <param name="tagName"></param>
private XmlNode GetOrCreateXmlElement(XmlDocument xmlDoc, string elementName, string tagName)
{
if (xmlDoc == null || elementName.IsNullOrEmpty() || tagName.IsNullOrEmpty())
return null;
// first try find existing element
var mainTag = xmlDoc.GetElementsByTagName(tagName).Cast<XmlNode>().FirstOrDefault();
if (mainTag == null)
{
// add it in the root of the doc
var root = xmlDoc.FirstChild ?? xmlDoc.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, "configuration", ""));
mainTag = root.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, tagName, ""));
}
var addNodes = mainTag.ChildNodes.Cast<XmlNode>().Where(n => n.Name == "add");
var myNode = addNodes.Where(n => n.Attributes["key"].Value == elementName).FirstOrDefault();
if (myNode == null)
{
myNode = xmlDoc.CreateNode(XmlNodeType.Element, "add", "");
var xmlKey = xmlDoc.CreateAttribute("key");
var xmlValue = xmlDoc.CreateAttribute("value");
xmlKey.Value = elementName;
myNode.Attributes.Append(xmlKey);
myNode.Attributes.Append(xmlValue);
mainTag.InsertAfter(myNode, mainTag.LastChild);
}
return myNode;
}
/// <summary>
/// Adds or updates a setting in the specified config file
/// </summary>
/// <param name="fileName"></param>
/// <param name="key"></param>
/// <param name="value"></param>
public void CreateOrUpdateSetting(string fileName, string key, string value)
{
XmlNode appSettingValueNode;
var xmlDoc = GetXmlDoc(fileName, key, out appSettingValueNode);
if (xmlDoc == null)
return; // we don't necessarily need to find the app settings value node; we might still need to add it.
if (appSettingValueNode == null)
{
// add vplan element to config file
var appSettingNode = GetOrCreateXmlElement(xmlDoc, key, "appSettings");
appSettingValueNode = appSettingNode.Attributes.NullOr(a => a.GetNamedItem("value"));
}
var oldValue = appSettingValueNode.Value;
// save only when changed
if (string.Compare(oldValue, value, true) == 0)
return;
_allSettings[key] = value;
appSettingValueNode.Value = value;
try
{
xmlDoc.Save(fileName);
}
catch (Exception ex)
{
//ERROR Message here - LOG
Log.ErrorMessage("Error Creating or Updating CommonConfig File.", ex);
}
}
/// <summary>
/// Returns a setting from the config file, or null if setting not found.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string GetSetting(string key)
{
string value;
return _allSettings.TryGetValue(key, out value) ? value : null;
}
/// <summary>
/// Returns a setting from the specified xml file, or null if setting not found.
/// </summary>
/// <param name="fileName"></param>
/// <param name="key"></param>
/// <returns></returns>
public string GetSetting(string fileName, string key)
{
var cfg = new CommonConfig();
cfg.LoadFile(fileName);
string value;
return cfg._allSettings.TryGetValue(key, out value) ? value : null;
}
#endregion
#region CommonConfig file
/// <summary>
/// read %FileName%.config
/// </summary>
/// <returns>IConfig</returns>
public void ReadGlobalConfigFile()
{
Read(GlobalConfigFile);
}
/// <summary>
/// read %FileName%.config
/// </summary>
/// <param name="fileName">file name</param>
/// <returns>IConfig</returns>
public void Read(string fileName)
{
LoadFile(fileName);
}
/// <summary>
/// Loads the file.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <exception cref="System.Exception"></exception>
public void LoadFile(string fileName)
{
if (!File.Exists(fileName))
return;
using (XmlReader xmlReader = new XmlTextReader(fileName))
{
try
{
// create XML reader
XmlDocument xmlDoc = new XmlDocument();
// load file
xmlDoc.Load(xmlReader);
// parse file
XmlNodeList appSettingNodes = xmlDoc.SelectNodes("/configuration/appSettings/add");
// loop nodes
string key = null;
if (appSettingNodes != null)
{
foreach (XmlNode appSettingNode in appSettingNodes)
{
var attributes = appSettingNode.Attributes;
if (attributes != null) key = attributes.GetNamedItem("key").Value;
if (appSettingNode.Attributes == null || key == null)
continue;
var val = appSettingNode.Attributes.GetNamedItem("value").Value;
_allSettings[key] = val;
switch (key.ToLower())
{
case "addparametertest":
break;
}
}
}
}
catch (Exception exception)
{
throw new Exception(string.Format("CommonConfig file is corrupted", Environment.NewLine, exception.Message));
}
finally
{
xmlReader.Close();
}
}
}
/// <summary>
/// Updates the configuration parameter.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="parameter">The parameter.</param>
/// <param name="value">The value.</param>
public void UpdateConfigParameter(string fileName, string parameter, string value)
{
CreateOrUpdateSetting(fileName, parameter, value);
}
#endregion
}
}