IfcDoc.FormEdit.ValidateConcept C# (CSharp) Method

ValidateConcept() private method

Recursively validates a concept and all referenced concepts
private ValidateConcept ( DocTemplateUsage docUsage, DocModelView docView, DocExchangeRequirementEnum reqInherit, Type typeEntity, List list, StringBuilder sb, Type>.Dictionary typemap, int &grandtotalpass, int &grandtotalskip, int &grandtotallist ) : void
docUsage DocTemplateUsage The concept to validate
docView DocModelView The model view containing the concept
reqInherit DocExchangeRequirementEnum For a referenced concept, indicates requirements defined by the referencing (outer) concept.
typeEntity Type The compiled type corresponding to entity.
list List List of entities to test for concept.
sb StringBuilder String builder to append for reporting results.
typemap Type>.Dictionary Map of identifiers to compiled types
grandtotalpass int The total tests passing (less than or equal to total tests executed).
grandtotalskip int
grandtotallist int The total tests executed.
return void
        private void ValidateConcept(DocTemplateUsage docUsage, DocModelView docView, DocExchangeRequirementEnum reqInherit, Type typeEntity, List<SEntity> list, StringBuilder sb, Dictionary<string, Type> typemap, ref int grandtotalpass, ref int grandtotalskip, ref int grandtotallist)
        {
            if (docUsage.Definition == null || docUsage.Definition.IsDisabled || docUsage.Suppress)
                return;

            DocExchangeRequirementEnum req = DocExchangeRequirementEnum.NotRelevant;
            bool includeconcept = true;
            if (this.m_filterexchange != null)
            {
                includeconcept = false;
                foreach (DocExchangeItem ei in docUsage.Exchanges)
                {
                    if (ei.Exchange == this.m_filterexchange && ei.Applicability == DocExchangeApplicabilityEnum.Export &&
                        (ei.Requirement == DocExchangeRequirementEnum.Mandatory || ei.Requirement == DocExchangeRequirementEnum.Optional))
                    {
                        includeconcept = true;
                        req = ei.Requirement;
                    }
                }
            }
            else
            {
                // check net requirement if mandatory for any exchange
                foreach (DocExchangeItem docExchangeItem in docUsage.Exchanges)
                {
                    switch (docExchangeItem.Requirement)
                    {
                        case DocExchangeRequirementEnum.Mandatory:
                            req = DocExchangeRequirementEnum.Mandatory;
                            break;

                        case DocExchangeRequirementEnum.Optional:
                            if (req == DocExchangeRequirementEnum.NotRelevant)
                            {
                                req = DocExchangeRequirementEnum.Optional;
                            }
                            break;

                        case DocExchangeRequirementEnum.Excluded:
                            if (req == DocExchangeRequirementEnum.NotRelevant)
                            {
                                req = DocExchangeRequirementEnum.Excluded;
                            }
                            break;
                    }
                }
            }

            if (req == DocExchangeRequirementEnum.NotRelevant)
            {
                req = reqInherit;
                if (reqInherit != DocExchangeRequirementEnum.NotRelevant)
                {
                    includeconcept = true;
                }
            }

            if (!includeconcept)
                return;

            if (list.Count == 0)
            {
                sb.Append("<details><summary>");
                sb.Append(docUsage.Definition.Name);
                sb.AppendLine("</summary></details>");
                return;
            }

            StringBuilder sbDetail = new StringBuilder();

            if (docUsage.Definition != null && docUsage.Definition.Rules != null)
            {
                // new-style validation -- compiled code (fast)
                string methodname = DocumentationISO.MakeLinkName(docView) + "_" + DocumentationISO.MakeLinkName(docUsage.Definition);
                System.Reflection.MethodInfo method = typeEntity.GetMethod(methodname);

                int fail = 0;
                int pass = 0; // pass graph check
                int passRule = 0; // pass rule check
                int failRule = 0; // fail rule check
                List<DocModelRule> trace = new List<DocModelRule>();

                DocModelRule[] parameterrules = docUsage.Definition.GetParameterRules();
                Dictionary<DocModelRuleAttribute, bool> conditions = new Dictionary<DocModelRuleAttribute, bool>();

                if (docUsage.Definition.Name.Contains("-086"))
                {
                    this.ToString();
                }

                foreach (SEntity ent in list)
                {
                    if(docUsage.Definition.Name.Contains("-077") && ent.GetType().Name.Equals("IfcWindow"))
                    {
                        this.ToString();
                    }

                    object[] args = new object[0];
                    if (parameterrules != null && parameterrules.Length > 0)
                    {
                        args = new object[parameterrules.Length];

                        foreach (DocTemplateItem docItem in docUsage.Items)
                        {
                            //if (!docItem.Optional)
                            {
                                trace.Clear();
                                conditions.Clear();

                                if (docItem == docUsage.Items[0])
                                {
                                    sbDetail.Append("<tr valign=\"top\"><td rowspan=\"" + docUsage.Items.Count + "\">#");
                                    sbDetail.Append(ent.OID);
                                    sbDetail.Append("</td>");
                                }
                                else
                                {
                                    sbDetail.Append("<tr valign=\"top\">");
                                }

                                for (int iParam = 0; iParam < parameterrules.Length; iParam++)
                                {
                                    DocModelRule prule = parameterrules[iParam];

                                    sbDetail.Append("<td>");
                                    DocTemplateUsage docUsageInner = docItem.GetParameterConcept(prule.Identification, null);//verify...
                                    if (docUsageInner != null)
                                    {
                                        // report inner rules...
                                        foreach (DocTemplateItem docItemInner in docUsageInner.Items)
                                        {
                                            sbDetail.Append(docItemInner.RuleParameters);
                                            if (docItemInner.Optional)
                                            {
                                                sbDetail.Append("*");
                                            }
                                            sbDetail.Append("<br/>");
                                        }
                                    }
                                    else
                                    {
                                        string pval = docItem.GetParameterValue(prule.Identification);
                                        sbDetail.Append(pval);
                                    }
                                    sbDetail.Append("</td>");
                                }

                                sbDetail.Append("<td>");
                                bool? result = true;
                                foreach (DocModelRule rule in docUsage.Definition.Rules)
                                {
                                    trace.Clear();
                                    bool? itemresult = rule.Validate(ent, docItem, typemap, trace, ent, docUsage, conditions);
                                    if (itemresult != null && !itemresult.Value && result != null)
                                    {
                                        result = false;

                                        // check if conditions were all met; if not, then not a failure
                                        foreach(DocModelRule checkparam in parameterrules)
                                        {
                                            if(checkparam.IsCondition())
                                            {
                                                bool paramspec = false;
                                                if (!conditions.TryGetValue((DocModelRuleAttribute)checkparam, out paramspec) || paramspec == false)
                                                {
                                                    result = null;
                                                    break;
                                                }
                                            }
                                        }

                                        break;
                                    }
                                    else if (itemresult == null)
                                    {
                                        result = null; //verify: was commented out -- put back in to indicate that entire rule is inapplicable.
                                    }
                                }

                                if (result != null && !result.Value)
                                {
                                    foreach (DocModelRule mm in trace)
                                    {
                                        if (mm is DocModelRuleEntity)
                                        {
                                            sbDetail.Append("\\");
                                        }
                                        else if (mm is DocModelRuleAttribute)
                                        {
                                            sbDetail.Append(".");
                                        }
                                        sbDetail.Append(mm.Name);
                                    }

                                    docItem.ValidationStructure[ent] = false;

            #if false // don't mark overall usage as failure, since operator may only require one to be true
                                    if (!docItem.Optional)
                                    {
                                        docUsage.ValidationStructure[ent] = false;
                                        docUsage.Validation = false;
                                        docUsage.Definition.Validation = false;
                                        fail++;
                                    }
            #endif
                                }
                                else if (result != null && result.Value)
                                {
                                    // check for any nested failures
                                    foreach (DocTemplateUsage docInnerConcept in docItem.Concepts)
                                    {
                                        foreach (DocTemplateItem docInnerItem in docInnerConcept.Items)
                                        {
                                            bool innerresult = false;
                                            if(docInnerItem.ValidationStructure.TryGetValue(ent, out innerresult))
                                            {
                                                if(!innerresult)
                                                {
                                                    sbDetail.Append("~");
                                                    sbDetail.Append(docInnerItem.RuleParameters);
                                                    sbDetail.Append("<br/>");

                                                    result = false;
                                                    fail++;
                                                    break;
                                                }
                                            }
                                        }
                                    }

                                    if (result != null && result.Value)
                                    {
                                        sbDetail.Append("+");
                                        pass++;

                                        docItem.ValidationStructure[ent] = true;
                                        if (!docUsage.ValidationStructure.ContainsKey(ent)) // if no failures so far, then concept passes for now
                                        {
                                            docUsage.ValidationStructure[ent] = true;
                                        }
                                    }
                                }
                                else if (result == null)
                                {
                                    sbDetail.Append("*"); // NOT APPLICABLE

                                    // new V9.5: don't mark non-applicable as passing
                                    /*
                                    docItem.ValidationStructure[ent] = true;
                                    if (!docUsage.ValidationStructure.ContainsKey(ent))
                                    {
                                        docUsage.ValidationStructure[ent] = true;
                                    }*/
                                }

                                sbDetail.Append("</td><td>");

                                if (result == null)
                                {
                                    // don't evaluate constraint if it doesn't apply
                                }
                                else if (method != null)
                                {
                                    try
                                    {
                                        bool[] ruleresult = (bool[])method.Invoke(ent, null);//, args);
                                        if (ruleresult != null)
                                        {
                                            bool allpass = true;
                                            foreach (bool compresult in ruleresult)
                                            {
                                                if (!compresult)
                                                {
                                                    allpass = false;
                                                    break;
                                                }
                                            }

                                            if (allpass)
                                            {
                                                sbDetail.Append("+");
                                                passRule++;

                                                docUsage.ValidationConstraints[ent] = true;

                                                if (docUsage.Validation == null)
                                                {
                                                    docUsage.Validation = true;
                                                }
                                            }
                                            else
                                            {
                                                // run detailed report
                                                foreach (DocModelRule rule in docUsage.Definition.Rules)
                                                {
                                                    TraceRule(docUsage.Definition, rule, sbDetail, ent, list);
                                                }

                                                failRule++;

                                                docUsage.ValidationConstraints[ent] = false;
                                                docUsage.Validation = false;
                                            }
                                        }
                                        else
                                        {
                                            sbDetail.Append("FAIL");
                                            failRule++;
                                        }
                                    }
                                    catch (System.Reflection.TargetInvocationException et)
                                    {
                                        sbDetail.Append(et.InnerException.GetType().Name);
                                        failRule++;
                                    }
                                    catch (Exception ex)
                                    {
                                        sbDetail.Append(ex.GetType().Name);
                                        failRule++;
                                    }
                                }
                                else
                                {
                                    sbDetail.Append("FAIL - Incompatible Template");
                                }

                                sbDetail.AppendLine("</td></tr>");
                            }
                        }

                        // capture items that didn't match
                    }
                    else
                    {
                        // check for if there are no parameters

                        sbDetail.Append("<tr valign=\"top\"><td>#");
                        sbDetail.Append(ent.OID);
                        sbDetail.Append("</td><td>");

                        DocModelRule ruleFail = null;
                        bool? result = true;
                        foreach (DocModelRule rule in docUsage.Definition.Rules)
                        {
                            trace.Clear();
                            bool? itemresult = rule.Validate(ent, null, typemap, trace, ent, docUsage, conditions);
                            if (itemresult != null && !itemresult.Value)
                            {
                                result = false;
                            }
                            else if (itemresult == null)
                            {
                                result = null;
                            }

                            if (itemresult != null && !itemresult.Value)
                            {
                                if (ruleFail != null)
                                {
                                    sbDetail.Append("<br/>");
                                }
                                ruleFail = rule;

                                foreach (DocModelRule mm in trace)
                                {
                                    if (mm is DocModelRuleEntity)
                                    {
                                        sbDetail.Append("\\");
                                    }
                                    else if (mm is DocModelRuleAttribute)
                                    {
                                        sbDetail.Append(".");
                                    }
                                    sbDetail.Append(mm.Name);
                                }
                            }
                        }

                        if (result == null)
                        {
                            // no applicable rules, so passing
                            pass++;
                        }
                        else if (result != null && result.Value)
                        {
                            // all rules passed
                            docUsage.ValidationStructure[ent] = true;
                            if (docUsage.Validation == null)
                            {
                                docUsage.Validation = true;
                            }
                            pass++;
                        }
                        else if (ruleFail != null)
                        {
                            docUsage.ValidationStructure[ent] = false;
                            docUsage.Validation = false;
                            fail++;
                        }

                        if (result == null)
                        {
                            sbDetail.Append("*");
                        }
                        else if (ruleFail == null)
                        {
                            sbDetail.Append("+");
                        }

                        sbDetail.Append("</td><td>");

                        if (method != null)
                        {
                            try
                            {
                                bool[] ruleresult = (bool[])method.Invoke(ent, args);
                                if (ruleresult != null)
                                {
                                    bool allpass = true;
                                    foreach (bool compresult in ruleresult)
                                    {
                                        if (!compresult)
                                        {
                                            allpass = false;
                                            break;
                                        }
                                    }

                                    if (allpass)
                                    {
                                        sbDetail.Append("+");
                                        docUsage.ValidationConstraints[ent] = true;
                                        passRule++;
                                    }
                                    else
                                    {
                                        // run second-stage validation and trace
                                        bool debugpass = true;
                                        StringBuilder sbCheck = new StringBuilder();
                                        foreach (DocModelRule rule in docUsage.Definition.Rules)
                                        {
                                            bool eachpass = TraceRule(docUsage.Definition, rule, sbCheck, ent, list);
                                            if (!eachpass)
                                            {
                                                debugpass = false;
                                            }
                                        }
                                        if (!debugpass)
                                        {
                                            sbDetail.Append(sbCheck.ToString());
                                            docUsage.ValidationConstraints[ent] = false;
                                            docUsage.Validation = false;
                                            failRule++;
                                        }
                                        else
                                        {
                                            sbDetail.Append("+");
                                            docUsage.ValidationConstraints[ent] = true;
                                            if (docUsage.Validation == null)
                                            {
                                                docUsage.Validation = true;
                                            }
                                            passRule++;
                                        }
                                    }
                                }
                                else
                                {
                                    sbDetail.Append("FAIL");
                                    failRule++;
                                }
                            }
                            catch (System.Reflection.TargetInvocationException et)
                            {
                                sbDetail.Append(et.InnerException.GetType().Name);
                                failRule++;
                            }
                            catch (Exception ex)
                            {
                                sbDetail.Append(ex.GetType().Name);
                                failRule++;
                            }
                        }
                        else
                        {
                            sbDetail.Append("FAIL - Incompatible Template");
                        }
                        sbDetail.AppendLine("</td></tr>");
                    }

                }

                grandtotallist++;

                // nested concepts -- only one must pass
                StringBuilder sbNested = new StringBuilder();
                if (docUsage.Concepts.Count > 0)
                {
                    sbNested.AppendLine("<p>Validation of concept groups (only one must pass):</p>");

                    int subtotalpass = 0;
                    int subtotalskip = 0;
                    int subtotallist = 0;
                    foreach (DocTemplateUsage docSub in docUsage.Concepts)
                    {
                        ValidateConcept(docSub, docView, reqInherit, typeEntity, list, sbNested, typemap, ref subtotalpass, ref subtotalskip, ref subtotallist);
                    }

                    if (subtotalpass > 0)
                    {
                        //grandtotalpass++;
                        sbNested.AppendLine("<p>RESULT: PASS (" + subtotalpass + "/" + subtotallist + ")</p>");
                    }
                    else
                    {
                        fail++;
                        sbNested.AppendLine("<p>RESULT: FAIL (" + subtotalpass + "/" + subtotallist + ")</p>");
                    }
                }

                sb.AppendLine("<details><summary>" + docUsage.Definition.Name);

                sb.Append(" (Operator: " + docUsage.Operator.ToString() + ")");

                if(req == DocExchangeRequirementEnum.Optional)
                {
                    sb.Append(" [OPTIONAL]");
                }
                if (fail > 0 || failRule > 0)
                {
                    docUsage.Validation = false;
                    docUsage.Definition.Validation = false;

                    if(req == DocExchangeRequirementEnum.Optional)
                    {
                        grandtotalskip++;
                    }

                    sb.AppendLine(" - [FAIL]");
                }
                else
                {
                    docUsage.Validation = true;
                    if (docUsage.Definition.Validation == null)
                    {
                        docUsage.Definition.Validation = true;
                    }

                    grandtotalpass++;
                }

                sb.AppendLine("</summary>");
                sb.AppendLine("<table border=\"1\" >");
                sb.Append("<tr><th>Instance</th>");

                foreach (DocModelRule docRule in parameterrules)
                {
                    sb.Append("<th>");
                    sb.Append(docRule.Identification);

                    if (docRule.IsCondition())
                    {
                        sb.Append("?");
                    }

                    sb.Append("</th>");
                }

                sb.Append("<th>Structure</th>");
                sb.Append("<th>Constraints</th>");
                sb.AppendLine("</tr>");

                sb.AppendLine(sbDetail.ToString());

                sb.AppendLine("</table>");

                sb.AppendLine(sbNested.ToString());

                sb.AppendLine("</details>");
            }
        }
FormEdit