ActiveRecord based SettingsManager

By at July 17, 2007 09:39
Filed Under: Code
using System;
using System.Collections;
using System.Collections.Generic;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework.Config;
using NHibernate.Expression;

namespace SettingsManager
{
    public partial class SettingsManagerException : Exception
    {
        public SettingsManagerException(string message) : base(message)
        {
        }
    }

    public partial class SettingsManager
    {
        private const char BACKSLASH = '\x005c';

        public SettingsManager(string ConnectionString)
        {
            Hashtable properties = new Hashtable();
            properties.Add("hibernate.connection.driver_class", "NHibernate.Driver.SqlClientDriver");
            properties.Add("hibernate.dialect", "NHibernate.Dialect.MsSql2000Dialect");
            properties.Add("hibernate.connection.provider", "NHibernate.Connection.DriverConnectionProvider");
            properties.Add("hibernate.connection.connection_string", ConnectionString);
            InPlaceConfigurationSource source = new InPlaceConfigurationSource();
            source.Add(typeof (ActiveRecordBase), properties);
            ActiveRecordStarter.Initialize(source, typeof (Setting), typeof (Section));
            //ActiveRecordStarter.CreateSchema();
        }

        private static List<T> MakeList<T>(IList<T> sourceList)
        {
            List<T> resultList = sourceList as List<T>;
            if (resultList == null)
                resultList = new List<T>(sourceList);
            return resultList;
        }

        public void SetSetting<T>(string ApplicationName, string SectionPath, string SettingName, T SettingValue)
        {
            SetSetting<T>(ApplicationName, SectionPath, SettingName, SettingValue, DateTime.UtcNow.AddYears(1));
        }

        public void SetSetting<T>(string ApplicationName, string SectionPath, string SettingName, T SettingValue, DateTime ExpiresOnUTC)
        {
            SetSetting(ApplicationName,
                       SectionPath.Split(new char[] {BACKSLASH}, StringSplitOptions.RemoveEmptyEntries),
                       SettingName,
                       SettingValue,
                       ExpiresOnUTC);
        }

        private static Section GetSectionForApplication(string ApplicationName)
        {
            ICriterion[] criteria =
                new ICriterion[] {Expression.IsNull("ParentSection"), Expression.Eq("SectionName", ApplicationName)};
            return Section.FindOne(criteria);
        }

        public void SetSetting<T>(string ApplicationName,
                                  string[] SectionPath,
                                  string SettingName,
                                  T SettingValue,
                                  DateTime ExpiresOnUTC)
        {
            Section foundSection = GetSectionForApplication(ApplicationName);
            if (foundSection == null)
            {
                foundSection = new Section(ApplicationName, null);
                foundSection.Save();
                foundSection = GetSectionForApplication(ApplicationName);
            }
            Section prevSection = foundSection;
            foreach (string sectionPath in SectionPath)
            {
                foundSection =
                    MakeList(foundSection.Sections).Find(
                        delegate(Section sec) { return sec.SectionName.Equals(sectionPath); });
                if (foundSection == null)
                {
                    foundSection = new Section(sectionPath, prevSection);
                    foundSection.Save();
                }
                prevSection = foundSection;
            }
            Setting setting =
                MakeList(foundSection.Settings).Find(
                    delegate(Setting set) { return set.SettingName.Equals(SettingName); });
            if (setting == null)
            {
                setting = new Setting(SettingName, SettingValue.ToString(), ExpiresOnUTC);
                setting.Save();
                foundSection.Settings.Add(setting);
                foundSection.Save();
            }
            else
            {
                setting.SettingValue = SettingValue.ToString();
                setting.ExpiresOnUTC = ExpiresOnUTC;
                setting.Save();
            }
        }

        public T GetSetting<T>(string ApplicationName, string SectionPath, string SettingName)
        {
            return
                GetSetting<T>(ApplicationName,
                              SectionPath.Split(new char[] {BACKSLASH}, StringSplitOptions.RemoveEmptyEntries),
                              SettingName);
        }

        public T GetSetting<T>(string ApplicationName, string[] SectionPath, string SettingName)
        {
            Section foundSection = GetSectionForApplication(ApplicationName);
            foreach (string sectionPath in SectionPath)
            {
                foundSection =
                    MakeList(foundSection.Sections).Find(
                        delegate(Section sec) { return sec.SectionName.Equals(sectionPath); });
                if (foundSection == null)
                    throw new SettingsManagerException("Section not found.");
            }
            Setting setting =
                MakeList(foundSection.Settings).Find(
                    delegate(Setting set) { return set.SettingName.Equals(SettingName); });
            if (setting == null)
                throw new SettingsManagerException("Setting not found.");
            if (setting.ExpiresOnUTC < DateTime.UtcNow)
                throw new SettingsManagerException("Setting has expired.");
            return (T) (object) setting.SettingValue;
        }

        public void DeleteSetting(string ApplicationName, string SectionPath, string SettingName)
        {
            DeleteSetting(ApplicationName,
                          SectionPath.Split(new char[] {BACKSLASH}, StringSplitOptions.RemoveEmptyEntries),
                          SettingName);
        }

        public void DeleteSetting(string ApplicationName, string[] SectionPath, string SettingName)
        {
            Section foundSection = GetSectionForApplication(ApplicationName);
            foreach (string sectionPath in SectionPath)
            {
                foundSection =
                    MakeList(foundSection.Sections).Find(
                        delegate(Section sec) { return sec.SectionName.Equals(sectionPath); });
                if (foundSection == null)
                    throw new SettingsManagerException("Section not found.");
            }
            Setting setting =
                MakeList(foundSection.Settings).Find(
                    delegate(Setting set) { return set.SettingName.Equals(SettingName); });
            if (setting != null)
                setting.Delete();
        }

        public Dictionary<string, string> GetAllSettings(string ApplicationName, string SectionPath)
        {
            return
                GetAllSettings(ApplicationName,
                               SectionPath.Split(new char[] {BACKSLASH}, StringSplitOptions.RemoveEmptyEntries));
        }

        public Dictionary<string, string> GetAllSettings(string ApplicationName, string[] SectionPath)
        {
            Dictionary<string, string> returnDic = new Dictionary<string, string>();
            Section foundSection = GetSectionForApplication(ApplicationName);
            foreach (string sectionPath in SectionPath)
            {
                foundSection =
                    MakeList(foundSection.Sections).Find(
                        delegate(Section sec) { return sec.SectionName.Equals(sectionPath); });
                if (foundSection == null)
                    throw new SettingsManagerException("Section not found.");
            }

            foreach (Setting setting in foundSection.Settings)
                returnDic.Add(string.Concat(foundSection.SectionName, BACKSLASH, setting.SettingName), setting.SettingValue);
            foreach (Section section in foundSection.Sections)
                TraverseSection(section, returnDic);

            return returnDic;
        }

        private static void TraverseSection(Section section, Dictionary<string, string> dic)
        {
            if (section.Sections.Count >= 1)
                foreach (Section sec in section.Sections)
                    TraverseSection(sec, dic);
            else
                foreach (Setting setting in section.Settings)
                    dic.Add(string.Concat(section.SectionName, BACKSLASH, setting.SettingName), setting.SettingValue);
        }
    }

    [ActiveRecord("Section", Schema = "dbo")]
    internal partial class Section : ActiveRecordBase<Section>
    {
        private Section _parentsection;
        private int _sectionId;
        private string _sectionName;
        private IList<Section> _sections = new List<Section>();
        private IList<Setting> _settings = new List<Setting>();

        public Section()
        {
        }

        public Section(string SectionName, Section ParentSection)
        {
            _sectionName = SectionName;
            _parentsection = ParentSection;
        }

        [Property("SectionName", ColumnType = "String", NotNull = true)]
        public virtual string SectionName { get { return _sectionName; } set { _sectionName = value; } }

        [PrimaryKey(PrimaryKeyType.Identity, "SectionId", ColumnType = "Int32")]
        public virtual int SectionId { get { return _sectionId; } set { _sectionId = value; } }

        [HasMany(typeof (Section), ColumnKey = "ParentSectionId", Table = "Section")]
        public virtual IList<Section> Sections { get { return _sections; } set { _sections = value; } }

        [BelongsTo("ParentSectionId", NotNull = false)]
        public virtual Section ParentSection { get { return _parentsection; } set { _parentsection = value; } }

        [HasAndBelongsToMany(typeof (Setting), ColumnRef = "SettingId", ColumnKey = "SectionId", Schema = "dbo",
            Table = "SectionSetting")]
        public virtual IList<Setting> Settings { get { return _settings; } set { _settings = value; } }
    }

    [ActiveRecord("Setting", Schema = "dbo")]
    internal partial class Setting : ActiveRecordBase<Setting>
    {
        private DateTime _expiresOnUTC;
        private IList<Section> _sections = new List<Section>();
        private int _settingId;
        private string _settingName;
        private string _settingValue;

        public Setting()
        {
        }

        public Setting(string SettingName, string SettingValue, DateTime ExpiresOnUTC)
        {
            _settingName = SettingName;
            _settingValue = SettingValue;
            _expiresOnUTC = ExpiresOnUTC;
        }

        [Property("SettingName", ColumnType = "String", NotNull = true)]
        public virtual string SettingName { get { return _settingName; } set { _settingName = value; } }

        [Property("SettingValue", ColumnType = "String", NotNull = true)]
        public virtual string SettingValue { get { return _settingValue; } set { _settingValue = value; } }

        [Property("ExpiresOnUTC", ColumnType = "Timestamp", NotNull = true)]
        public virtual DateTime ExpiresOnUTC { get { return _expiresOnUTC; } set { _expiresOnUTC = value; } }

        [PrimaryKey(PrimaryKeyType.Identity, "SettingId", ColumnType = "Int32")]
        public virtual int SettingId { get { return _settingId; } set { _settingId = value; } }

        [HasAndBelongsToMany(typeof (Section), ColumnRef = "SectionId", ColumnKey = "SettingId", Schema = "dbo",
            Table = "SectionSetting")]
        public virtual IList<Section> Sections { get { return _sections; } set { _sections = value; } }
    }
}

Comments

4/22/2010 11:46:18 AM #

Cloud Hosting

Database code is always tricky.  However, when it works it can save hours of time.  You want to make sure you get it right on the front end.  Trying to fix a problem after the fact that be a real headache.  Thanks for the post.

Cloud Hosting United States | Reply

4/24/2010 2:07:11 AM #

watch eclipse online

Hi what theme are you using for your site? Can you email me at Dudek@yahoo.com thanks

watch eclipse online United States | Reply

6/2/2010 2:42:32 PM #

how do they work

Fantastic blog!  I dont think Ive seen all the angles of this subject the way youve pointed them out.  Youre a true star, a rock star man.  Youve got so much to say and know so much about the subject that I think you should just teach a class about it...HaHa!

how do they work United States | Reply

6/2/2010 10:49:38 PM #

Search Engine Marketing Seattle

I dont know what it is about this blog that turns me off so much, but you just dont seem to get me excited.  I dont know if its the lack of content or just the way you wrote it.  But you really dont seem to understand that your readers may not agree with you.  Youre really just too out there for me.

Search Engine Marketing Seattle United States | Reply

6/3/2010 1:59:10 AM #

Cosmetic Dentist Tacoma

Great job here.  I really enjoyed what you had to say.  Keep going because you definitely bring a new voice to this subject.  Not many people would say what youve said and still make it interesting.  Well, at least Im interested.  Cant wait to see more of this from you.

Cosmetic Dentist Tacoma United States | Reply

6/6/2010 4:16:35 PM #

Coach Signature

You...are...awesome!  This blog is so great.  I really hope more people read this and get what youre saying, because let me tell you, its important stuff.  I never wouldve thought about it this way unless Id run into your blog.  Thanks for putting it up.  I hope you have great success.

Coach Signature United States | Reply

6/28/2010 6:50:00 PM #

paid to click

this is "ActiveRecord based SettingsManager" exactly what I am looking for. thanks for this post.

paid to click United States | Reply

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading