// Factories...
 public static ChangeSet FromCurrentConfiguration()
 {
     return(new ChangeSet(
                RecognizedSettings
                .Where(setting => !setting.IsAccessDisallowed)
                .ToDictionary(setting => setting.Name, setting => setting.GetValue())
                ));
 }
        // If 'null' return, then error was encountered, and offending messages already logged...
        // Otherwise, a (possibly empty) ChangeSet is returned.
        public static ChangeSet FromXmlAttributes(Dictionary <string, string> attributes)
        {
            try
            {
                var attributesToProcess =
                    (from attribute in attributes
                     where
                     RecognizedSettings.Any(setting => (setting.Name == attribute.Key) && !setting.IsAccessDisallowed)
                     select attribute)
                    .ToDictionary(attribute => attribute.Key, attribute => (object)attribute.Value);

                return(new ChangeSet(attributesToProcess));
            }

            catch (Exception)
            {
                // empty
            }

            return(null);
        }
        public ChangeSet(Dictionary <string, object> changes)
        {
            var changeSet          = new List <Tuple <SettingDescriptor, object> >();
            var isProblemAttribute = false;

            foreach (var change in changes)
            {
                try
                {
                    var name  = change.Key;
                    var value = change.Value;

                    // Setting name cannot be null or empty...
                    if (string.IsNullOrEmpty(name))
                    {
                        QBCLog.Error("Name may not be null or empty");
                        isProblemAttribute = true;
                        continue;
                    }

                    // Check that setting exists...
                    var settingDescriptor = RecognizedSettings.FirstOrDefault(s => s.Name == name);
                    if (settingDescriptor == null)
                    {
                        QBCLog.Error("Unable to locate setting for '{0}'.", name);
                        isProblemAttribute = true;
                        continue;
                    }

                    // Is changing attribute allowed?
                    if (settingDescriptor.IsAccessDisallowed)
                    {
                        QBCLog.Error("Accessing attribute '{0}' is not allowed.", name);
                        isProblemAttribute = true;
                        continue;
                    }

                    // Check that setting doesn't already exist in the changeset...
                    if (changeSet.Any(t => t.Item1.Name == name))
                    {
                        QBCLog.Error("Setting '{0}' already exists in the changeset.", name);
                        isProblemAttribute = true;
                        continue;
                    }

                    // If user specified 'original' value, go look it up and substitute it for 'value'...
                    if ((value is string) && ((string)value == "original"))
                    {
                        object originalValue;

                        if (!OriginalConfiguration.TryGetValue(settingDescriptor.Name, out originalValue))
                        {
                            // A missing 'original configuration' is a maintenance issue, not a user error...
                            QBCLog.MaintenanceError("For setting '{0}', there is no original configuration value.",
                                                    settingDescriptor.Name);
                            isProblemAttribute = true;
                            continue;
                        }

                        value = originalValue;
                    }

                    // Check that setting is an appropriate type...
                    var newValue = settingDescriptor.ToCongruentObject(value);

                    if (!settingDescriptor.ConstraintChecker.IsWithinConstraints(newValue))
                    {
                        QBCLog.Error("For setting '{0}', the provided value '{1}' is not within the required constraints of {2}.",
                                     name, value, settingDescriptor.ConstraintChecker.Description);
                        isProblemAttribute = true;
                        continue;
                    }

                    // Setting change is acceptable...
                    changeSet.Add(Tuple.Create(settingDescriptor, value));
                }

                catch (Exception ex)
                {
                    QBCLog.Exception(ex, "MAINTENANCE ERROR: Error processing attribute '{0}.'", change.Key);
                    isProblemAttribute = true;
                }
            }

            // If problem encountered with any change, we're unable to build the ChangeSet...
            if (isProblemAttribute)
            {
                _changeSet = null;
                throw new ArgumentException("Problems encountered with provided argument");
            }

            Count      = changeSet.Count;
            _changeSet = new ReadOnlyCollection <Tuple <SettingDescriptor, object> >(changeSet);
        }