コード例 #1
0
ファイル: Validator.cs プロジェクト: jonthysell/TEGS
        public static IReadOnlyList <ValidationError> Validate(Graph graph)
        {
            if (graph is null)
            {
                throw new ArgumentNullException(nameof(graph));
            }

            var scriptingHost             = MakeValidationScriptingHost();
            List <ValidationError> errors = new List <ValidationError>();

            // Verify state variables

            Dictionary <string, List <StateVariable> > uniqueStateVariableNames = new Dictionary <string, List <StateVariable> >();

            HashSet <StateVariable> badStateVariables = new HashSet <StateVariable>();

            foreach (StateVariable sv in graph.StateVariables)
            {
                // Verify name
                if (string.IsNullOrWhiteSpace(sv.Name))
                {
                    errors.Add(new BlankStateVariableNameValidationError(graph, sv));
                    badStateVariables.Add(sv);
                }
                else
                {
                    if (!uniqueStateVariableNames.ContainsKey(sv.Name))
                    {
                        uniqueStateVariableNames[sv.Name] = new List <StateVariable>();
                    }

                    uniqueStateVariableNames[sv.Name].Add(sv);

                    if (ScriptingHost.ReservedKeywords.Contains(sv.Name))
                    {
                        errors.Add(new ReservedKeywordStateVariableValidationError(graph, sv));
                        badStateVariables.Add(sv);
                    }
                    else if (!ScriptingHost.IsValidSymbolName(sv.Name, false))
                    {
                        errors.Add(new InvalidStateVariableNameValidationError(graph, sv));
                        badStateVariables.Add(sv);
                    }
                }
            }

            foreach (var kvp in uniqueStateVariableNames)
            {
                if (kvp.Value.Count > 1)
                {
                    errors.Add(new DuplicateStateVariableNamesValidationError(graph, kvp.Value));
                    foreach (StateVariable sv in kvp.Value)
                    {
                        badStateVariables.Add(sv);
                    }
                }
            }

            foreach (StateVariable sv in graph.StateVariables)
            {
                if (!badStateVariables.Contains(sv))
                {
                    scriptingHost.Create(sv);
                }
            }

            // Verify verticies
            List <Vertex> startingVerticies = new List <Vertex>();

            Dictionary <string, List <Vertex> > uniqueVertexNames = new Dictionary <string, List <Vertex> >();

            foreach (Vertex v in graph.Verticies)
            {
                if (v.IsStartingVertex)
                {
                    startingVerticies.Add(v);
                }

                // Verify name
                if (string.IsNullOrWhiteSpace(v.Name))
                {
                    errors.Add(new BlankVertexNameValidationError(graph, v));
                }
                else
                {
                    if (!uniqueVertexNames.ContainsKey(v.Name))
                    {
                        uniqueVertexNames[v.Name] = new List <Vertex>();
                    }

                    uniqueVertexNames[v.Name].Add(v);
                }

                // Verify parameters
                IReadOnlyList <string> parameterNames = v.ParameterNames;

                if (parameterNames is not null)
                {
                    foreach (string parameterName in parameterNames)
                    {
                        if (!graph.HasStateVariable(parameterName))
                        {
                            errors.Add(new InvalidParameterNameVertexValidationError(graph, v, parameterName));
                        }
                    }
                }

                // Verify code
                string[] code = v.Code;
                if (code is not null && code.Length > 0)
                {
                    for (int i = 0; i < code.Length; i++)
                    {
                        try
                        {
                            scriptingHost.Execute(code[i]);
                        }
                        catch (Exception ex)
                        {
                            errors.Add(new InvalidCodeVertexValidationError(graph, v, code[i], ex.Message));
                        }
                    }
                }
            }

            if (startingVerticies.Count == 0)
            {
                errors.Add(new NoStartingVertexValidationError(graph));
            }
            else if (startingVerticies.Count > 1)
            {
                errors.Add(new MultipleStartingVertexValidationError(graph, startingVerticies));
            }

            foreach (var kvp in uniqueVertexNames)
            {
                if (kvp.Value.Count > 1)
                {
                    errors.Add(new DuplicateVertexNamesValidationError(graph, kvp.Value));
                }
            }

            // Verify edges
            foreach (Edge e in graph.Edges)
            {
                bool validVerticies = true;
                if (e.Source is null)
                {
                    errors.Add(new SourceMissingEdgeValidationError(graph, e));
                    validVerticies = false;
                }

                if (e.Target is null)
                {
                    errors.Add(new TargetMissingEdgeValidationError(graph, e));
                    validVerticies = false;
                }

                if (validVerticies)
                {
                    if (e.Action == EdgeAction.Schedule)
                    {
                        var parameterNames       = e.Target.ParameterNames;
                        var parameterExpressions = e.ParameterExpressions;

                        if (parameterNames.Count > 0 && parameterExpressions.Count == 0)
                        {
                            errors.Add(new ParametersRequiredEdgeValidationError(graph, e));
                        }
                        else if (parameterExpressions.Count != parameterNames.Count)
                        {
                            errors.Add(new InvalidParametersEdgeValidationError(graph, e));
                        }

                        if (parameterExpressions.Count > 0)
                        {
                            for (int i = 0; i < parameterExpressions.Count; i++)
                            {
                                try
                                {
                                    var result = scriptingHost.Evaluate(parameterExpressions[i]);
                                    scriptingHost.SetVariable(parameterNames[i], result);
                                }
                                catch (Exception ex)
                                {
                                    errors.Add(new InvalidParameterEdgeValidationError(graph, e, parameterExpressions[i], ex.Message));
                                }
                            }
                        }
                    }

                    // Verify condition
                    try
                    {
                        scriptingHost.Evaluate(e.Condition, VariableValue.True).AsBoolean();
                    }
                    catch (Exception ex)
                    {
                        errors.Add(new InvalidConditionEdgeValidationError(graph, e, ex.Message));
                    }

                    // Verify delay
                    try
                    {
                        scriptingHost.Evaluate(e.Delay, new VariableValue(Schedule.DefaultDelay)).AsNumber();
                    }
                    catch (Exception ex)
                    {
                        errors.Add(new InvalidDelayEdgeValidationError(graph, e, ex.Message));
                    }

                    // Verify priority
                    try
                    {
                        scriptingHost.Evaluate(e.Priority, new VariableValue(Schedule.DefaultPriority)).AsNumber();
                    }
                    catch (Exception ex)
                    {
                        errors.Add(new InvalidPriorityEdgeValidationError(graph, e, ex.Message));
                    }
                }
            }

            return(errors);
        }