Example #1
0
 public static void LogCircularDependencyError <T>(DeferredLoadObject <T> loadObj)
 {
     LoggingUtil.LogError(loadObj.obj, loadObj.obj.ErrorPrefix(loadObj.configNode) + ": Error parsing " + loadObj.key + ": " +
                          "Circular dependency detected while parsing an expression (possible culprit(s): " +
                          string.Join(", ", loadObj.dependencies.ToArray()) + ").");
 }
Example #2
0
        /// <summary>
        /// Attempts to parse a value from the config node.  Returns a default value if not found.
        /// Validates return values using the given function.
        /// </summary>
        /// <typeparam name="T">The type of value to convert to.</typeparam>
        /// <param name="configNode">The ConfigNode to read from.</param>
        /// <param name="key">The key to examine.</param>
        /// <param name="setter">Function used to set the output value</param>
        /// <param name="obj">Factory object for error messages.</param>
        /// <param name="defaultValue">Default value to use if there is no key in the config node</param>
        /// <param name="validation">Validation function to run against the returned value</param>
        /// <returns>The parsed value (or default value if not found)</returns>
        public static bool ParseValue <T>(ConfigNode configNode, string key, Action <T> setter, IContractConfiguratorFactory obj, T defaultValue, Func <T, bool> validation)
        {
            // Initialize the data type of the expression
            if (currentDataNode != null && !currentDataNode.IsInitialized(key))
            {
                currentDataNode.BlankInit(key, typeof(T));
            }

            bool valid = true;
            T    value = defaultValue;

            if (configNode.HasValue(key) || configNode.HasNode(key))
            {
                try
                {
                    // Check whether there's a value
                    if (configNode.HasValue(key) && string.IsNullOrEmpty(configNode.GetValue(key)))
                    {
                        LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": Required value '" + key + "' is empty.");
                        valid = false;
                    }
                    else
                    {
                        // Load value
                        value = ParseValue <T>(configNode, key, true);
                    }

                    // If value was non-null, run validation
                    if (value != null && (typeof(T) != typeof(string) || ((string)(object)value) != ""))
                    {
                        try
                        {
                            valid = validation.Invoke(value);
                            if (!valid)
                            {
                                // In general, the validation function should throw an exception and give a much better message
                                LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": A validation error occured while loading the key '" + key + "' with value '" + value + "'.");
                            }
                        }
                        catch (Exception e)
                        {
                            if (e is DataNode.ValueNotInitialized)
                            {
                                throw;
                            }

                            LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": A validation error occured while loading the key '" + key + "' with value '" + value + "'.");
                            LoggingUtil.LogException(e);
                            valid = false;
                        }
                    }
                }
                catch (Exception e)
                {
                    if (e.GetType() == typeof(DataNode.ValueNotInitialized))
                    {
                        string dependency = ((DataNode.ValueNotInitialized)e).key;
                        string path       = currentDataNode.Path() + key;

                        LoggingUtil.LogVerbose(typeof(ConfigNodeUtil), "Trying to load " + path + ", but " + dependency + " is uninitialized.");

                        // Defer loading this value
                        DeferredLoadObject <T> loadObj = null;
                        if (!deferredLoads.ContainsKey(path) || deferredLoads[path].GetType().GetGenericArguments().First() != typeof(T))
                        {
                            deferredLoads[path] = new DeferredLoadObject <T>(configNode, key, setter, obj, validation, currentDataNode);
                        }
                        loadObj = (DeferredLoadObject <T>)deferredLoads[path];

                        // New dependency - try again
                        if (!loadObj.dependencies.Contains(dependency))
                        {
                            LoggingUtil.LogVerbose(typeof(ConfigNodeUtil), "    New dependency, will re-attempt to load later.");
                            loadObj.dependencies.Add(dependency);
                            return(true);
                        }
                    }

                    LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": Error parsing " + key);

                    // Return immediately on deferred load error
                    if (e.GetType() == typeof(DataNode.ValueNotInitialized))
                    {
                        DataNode.ValueNotInitialized vni = e as DataNode.ValueNotInitialized;
                        LoggingUtil.LogException(new Exception("Unknown identifier '@" + vni.key + "'."));
                        return(false);
                    }
                    LoggingUtil.LogException(e);

                    valid = false;
                }
                finally
                {
                    AddFoundKey(configNode, key);
                }
            }

            // Store the value
            if (currentDataNode != null)
            {
                currentDataNode[key] = value;

                if (!currentDataNode.IsDeterministic(key) && initialLoad)
                {
                    currentDataNode.DeferredLoads.Add(new DeferredLoadObject <T>(configNode, key, setter, obj, validation, currentDataNode));
                }
            }

            // Invoke the setter function
            if (valid)
            {
                setter.Invoke(value);
            }

            return(valid);
        }
Example #3
0
 public static bool ExecuteLoad <T>(DeferredLoadObject <T> loadObj)
 {
     SetCurrentDataNode(loadObj.dataNode);
     return(ParseValue <T>(loadObj.configNode, loadObj.key, loadObj.setter, loadObj.obj, loadObj.validation));
 }
Example #4
0
 public static IEnumerable <string> GetDependencies <T>(DeferredLoadObject <T> loadObj)
 {
     return(loadObj.dependencies);
 }
Example #5
0
        /// <summary>
        /// Attempts to parse a value from the config node.  Returns a default value if not found.
        /// Validates return values using the given function.
        /// </summary>
        /// <typeparam name="T">The type of value to convert to.</typeparam>
        /// <param name="configNode">The ConfigNode to read from.</param>
        /// <param name="key">The key to examine.</param>
        /// <param name="setter">Function used to set the output value</param>
        /// <param name="obj">Factory object for error messages.</param>
        /// <param name="defaultValue">Default value to use if there is no key in the config node</param>
        /// <param name="validation">Validation function to run against the returned value</param>
        /// <returns>The parsed value (or default value if not found)</returns>
        public static bool ParseValue <T>(ConfigNode configNode, string key, Action <T> setter, IContractConfiguratorFactory obj, T defaultValue, Func <T, bool> validation)
        {
            // Initialize the data type of the expression
            if (currentDataNode != null && !currentDataNode.IsInitialized(key))
            {
                currentDataNode.BlankInit(key, typeof(T));
            }

            bool valid = true;
            T    value = defaultValue;

            if (configNode.HasValue(key))
            {
                try
                {
                    // Load value
                    value = ParseValue <T>(configNode, key, true);

                    // If value was non-null, run validation
                    if (value != null)
                    {
                        try
                        {
                            valid = validation.Invoke(value);
                            if (!valid)
                            {
                                // In general, the validation function should throw an exception and give a much better message
                                LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": The value supplied for " + key + " (" + value + ") is invalid.");
                            }
                        }
                        catch (Exception e)
                        {
                            LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": The value supplied for " + key + " (" + value + ") is invalid.");
                            LoggingUtil.LogException(e);
                            valid = false;
                        }
                    }
                }
                catch (Exception e)
                {
                    if (e.GetType() == typeof(DataNode.ValueNotInitialized))
                    {
                        string dependency = ((DataNode.ValueNotInitialized)e).key;
                        string path       = currentDataNode.Path() + key;

                        LoggingUtil.LogVerbose(typeof(ConfigNodeUtil), "Trying to load " + key + ", but " + dependency + " is uninitialized.");

                        // Defer loading this value
                        DeferredLoadObject <T> loadObj = null;
                        if (!deferredLoads.ContainsKey(path))
                        {
                            deferredLoads[path] = new DeferredLoadObject <T>(configNode, key, setter, obj, validation, currentDataNode);
                        }
                        loadObj = (DeferredLoadObject <T>)deferredLoads[path];

                        // New dependency - try again
                        if (!loadObj.dependencies.Contains(dependency))
                        {
                            LoggingUtil.LogVerbose(typeof(ConfigNodeUtil), "    New dependency, will re-attempt to load later.");
                            loadObj.dependencies.Add(dependency);
                            return(true);
                        }
                    }

                    LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": Error parsing " + key);
                    LoggingUtil.LogException(e);

                    // Return immediately on deferred load error
                    if (e.GetType() == typeof(DataNode.ValueNotInitialized))
                    {
                        return(false);
                    }

                    valid = false;
                }
                finally
                {
                    AddFoundKey(configNode, key);
                }
            }

            // Store the value
            if (currentDataNode != null)
            {
                LoggingUtil.LogVerbose(typeof(ConfigNodeUtil), "DataNode[" + currentDataNode.Name + "], storing " + key + " = " + value);
                currentDataNode[key] = value;

                if (!currentDataNode.IsDeterministic(key) && initialLoad)
                {
                    currentDataNode.DeferredLoads.Add(new DeferredLoadObject <T>(configNode, key, setter, obj, validation, currentDataNode));
                }
            }

            // Invoke the setter function
            if (valid)
            {
                setter.Invoke(value);
            }

            return(valid);
        }