/// <param name="candidateParent">If null provides a missing match report</param>
        /// <param name="targetFacility">The target facility is required to ensure that the facility tree is properly referenced</param>
        /// <returns></returns>
        internal T Validate(T candidateParent, Facility targetFacility)
        {
            var         iSubmitted        = 0;
            var         iPassed           = 0;
            List <TSub> candidateChildren = null;
            var         returnChildren    = new List <TSub>();

            // initialisation
            var retType = targetFacility.Create <T>();

            retType.Categories = new List <Category>();
            retType.SetRequirementExternalSystem(_requirementObject.ExternalSystem);
            retType.SetRequirementExternalId(_requirementObject.ExternalId);
            retType.SetRequirementName(_requirementObject.Name);
            retType.SetRequirementCategories(_requirementObject.Categories);

            // improve returning Parent
            if (candidateParent == null) // the following properties depend on the nullity of candidate
            {
                retType.Name = _requirementObject.Name;
            }
            else
            {
                retType.Name           = candidateParent.Name;
                retType.ExternalId     = candidateParent.ExternalId;
                retType.ExternalSystem = candidateParent.ExternalSystem;
                retType.Categories     = candidateParent.Categories.Clone().ToList();
                candidateChildren      = candidateParent.GetChildObjects <TSub>();
                if (candidateChildren != null)
                {
                    iSubmitted = candidateChildren.Count;
                }
            }

            var returnWithoutFurtherTests = false;

            if (!RequirementDetails.Any())
            {
                retType.Description = "Classification has no requirements.\r\n";
                retType.Categories.Add(FacilityValidator.PassedCat);
                iPassed = iSubmitted;
                returnWithoutFurtherTests = true;
            }

            // if candidate is null then consider there's no match
            if (candidateParent == null)
            {
                // it's only a failure if the requirement was itself required (not only it had atteributes required)
                if (_requirementObject.Categories != null &&
                    _requirementObject.Categories.Any(c => c.Classification == "DPoW" && c.Code == "required")
                    )
                {
                    retType.Categories.Add(FacilityValidator.FailedCat);
                }
                else
                {
                    retType.Categories.Add(FacilityValidator.PassedCat);
                }
                retType.Description = "No candidates in submission match the required classification.\r\n";
                retType.Attributes.AddRange(RequirementAttributes());
                returnWithoutFurtherTests = true;
            }
            if (returnWithoutFurtherTests)
            {
                retType.SetSubmittedChildrenCount(iSubmitted);
                retType.SetValidChildrenCount(iPassed);
                return(retType);
            }

            // ==================== begin testing at parent level

            CachedPropertiesAndAttributesValidator <T> parentCachedValidator;

            try
            {
                parentCachedValidator = new CachedPropertiesAndAttributesValidator <T>(candidateParent);
            }
            catch (ValidationException ex)
            {
                retType.Categories.Add(FacilityValidator.FailedCat);
                retType.Description += ex.Message;
                return(retType);
            }

            if (retType.Attributes == null)
            {
                retType.Attributes = new List <Attribute>();
            }

            // produce parent level description
            var outstandingRequirementsCount = 0;



            foreach (var req in RequirementDetails)
            {
                object satValue;
                var    pass = parentCachedValidator.CanSatisfy(req, out satValue);
                var    a    = targetFacility.Clone(req.Attribute);

                // todo: determine the correct theoretical behaviour; it should probably be null, but needs changes in the reporting mechanism.
                // ReSharper disable once ConvertIfStatementToNullCoalescingExpression
                if (satValue != null)
                {
                    a.Value = AttributeValue.CreateFromObject(satValue);
                }
                else
                {
                    a.Value = AttributeValue.CreateFromObject("");
                }

                //// it was previously:
                //if (satValue is AttributeValue)
                //    a.Value = satValue as AttributeValue;
                //else
                //    a.Value = null;

                if (pass)
                {
                    a.Categories = new List <Category> {
                        FacilityValidator.PassedCat
                    };
                }
                else
                {
                    a.Categories = new List <Category> {
                        FacilityValidator.FailedCat
                    };
                    outstandingRequirementsCount++;
                }

                retType.Attributes.Add(a);
            }

            retType.Description = string.Format("{0} of {1} requirement addressed.", RequirementDetails.Count - outstandingRequirementsCount, RequirementDetails.Count);
            var anyChildFails = false;

            // ==================== begin testing at child level
            //
            if (candidateChildren != null)
            {
                foreach (var modelChild in candidateChildren)
                {
                    var iChildRequirementsMatched = 0;
                    var reportChild = targetFacility.Create <TSub>();
                    reportChild.Name       = modelChild.Name;
                    reportChild.ExternalId = modelChild.ExternalId;
                    reportChild.Categories = new List <Category>();
                    reportChild.Attributes = new List <Attribute>();

                    // child classification can be copied from model
                    //
                    if (modelChild.Categories != null)
                    {
                        reportChild.Categories.AddRange(modelChild.Categories);
                    }

                    var childCachedValidator = new CachedPropertiesAndAttributesValidator <TSub>(modelChild);
                    foreach (var req in RequirementDetails)
                    {
                        object satValue;
                        if (childCachedValidator.CanSatisfy(req, out satValue))
                        {
                            // passes locally
                            if (!parentCachedValidator.AlreadySatisfies(req))
                            {
                                iChildRequirementsMatched++;
                            }
                            var a = targetFacility.Clone(req.Attribute);
                            a.Value      = AttributeValue.CreateFromObject(satValue);
                            a.Categories = new List <Category> {
                                FacilityValidator.PassedCat
                            };
                            reportChild.Attributes.Add(a);
                        }
                        else if (!parentCachedValidator.AlreadySatisfies(req)) // fails locally, and is not passed at higher level, then add to explicit report fail
                        {
                            var a = targetFacility.Clone(req.Attribute);

                            // todo: determine the correct theoretical behaviour; it should probably be null, but needs changes in the reporting mechanism.

                            // ReSharper disable once ConvertIfStatementToNullCoalescingExpression
                            if (satValue != null)
                            {
                                a.Value = AttributeValue.CreateFromObject(satValue);
                            }
                            else
                            {
                                a.Value = AttributeValue.CreateFromObject("");
                            }


                            a.Categories = new List <Category> {
                                FacilityValidator.FailedCat
                            };
                            reportChild.Attributes.Add(a);
                        }
                    }

                    var sb = new StringBuilder();
                    sb.AppendFormat("{0} of {1} outstanding requirements addressed.", iChildRequirementsMatched, outstandingRequirementsCount);

                    var pass = (outstandingRequirementsCount == iChildRequirementsMatched);
                    if (!pass)
                    {
                        anyChildFails = true;
                        reportChild.Categories.Add(FacilityValidator.FailedCat);
                    }
                    else
                    {
                        iPassed++;
                        reportChild.Categories.Add(FacilityValidator.PassedCat);
                    }
                    reportChild.Description = sb.ToString();
                    returnChildren.Add(reportChild);
                }
            }
            retType.SetChildObjects(returnChildren);
            retType.Categories.Add(
                anyChildFails ? FacilityValidator.FailedCat : FacilityValidator.PassedCat
                );

            retType.SetSubmittedChildrenCount(iSubmitted);
            retType.SetValidChildrenCount(iPassed);
            return(retType);
        }
Beispiel #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="candidateType">If null provides a missing match report</param>
        /// <returns></returns>
        internal AssetType Validate(AssetType candidateType)
        {
            var iSubmitted = 0;
            var iPassed    = 0;

            // initialisation
            var retType = new AssetType
            {
                Categories = new List <Category>()
            };

            retType.SetRequirementExternalSystem(_requirementType.ExternalSystem);
            retType.SetRequirementExternalId(_requirementType.ExternalId);
            retType.SetRequirementName(_requirementType.Name);
            retType.SetRequirementCategories(_requirementType.Categories);

            // improve returning assetType
            if (candidateType == null) // the following properties depend on the nullity of candidate
            {
                retType.Name = _requirementType.Name;
            }
            else
            {
                retType.Name           = candidateType.Name;
                retType.ExternalId     = candidateType.ExternalId;
                retType.ExternalSystem = candidateType.ExternalSystem;
                retType.Categories     = candidateType.Categories.Clone().ToList();
                if (candidateType.Assets != null)
                {
                    iSubmitted = candidateType.Assets.Count;
                }
            }

            var returnWithoutFurtherTests = false;

            if (!RequirementDetails.Any())
            {
                retType.Description = "Classification has no requirements.\r\n";
                retType.Categories.Add(FacilityValidator.PassedCat);
                iPassed = iSubmitted;
                returnWithoutFurtherTests = true;
            }

            // if candidate is null then consider there's no match
            if (candidateType == null)
            {
                retType.Categories.Add(FacilityValidator.FailedCat);
                retType.Description = "No candidates in submission match the required classification.\r\n";
                retType.Attributes.AddRange(RequirementAttributes());
                returnWithoutFurtherTests = true;
            }

            if (returnWithoutFurtherTests)
            {
                retType.SetSubmittedAssetsCount(iSubmitted);
                retType.SetValidAssetsCount(iPassed);
                return(retType);
            }

            // ==================== begin Assets testing

            if (retType.Attributes == null)
            {
                retType.Attributes = new List <Attribute>();
            }

            // produce type level description
            var outstandingRequirementsCount = 0;

            var cachedValidator = new CachedPropertiesAndAttributesValidator <AssetType>(candidateType);

            foreach (var req in RequirementDetails)
            {
                object satValue;
                var    pass = cachedValidator.CanSatisfy(req, out satValue);
                var    a    = req.Attribute.Clone();
                if (satValue is AttributeValue)
                {
                    a.Value = satValue as AttributeValue;
                }
                else
                {
                    a.Value = null;
                }
                if (pass)
                {
                    a.Categories = new List <Category>()
                    {
                        FacilityValidator.PassedCat
                    };
                }
                else
                {
                    a.Categories = new List <Category>()
                    {
                        FacilityValidator.FailedCat
                    };
                    outstandingRequirementsCount++;
                }

                retType.Attributes.Add(a);
            }

            retType.Description = string.Format("{0} of {1} requirement addressed at type level.", RequirementDetails.Count - outstandingRequirementsCount, RequirementDetails.Count);

            var anyAssetFails = false;

            retType.Assets = new List <Asset>();
            // perform tests at asset level
            if (candidateType.Assets != null)
            {
                foreach (var modelAsset in candidateType.Assets)
                {
                    int iAssetRequirementsMatched = 0;
                    var reportAsset = new Asset
                    {
                        Name = modelAsset.Name,
                        // AssetIdentifier = modelAsset.AssetIdentifier,
                        ExternalId = modelAsset.ExternalId,
                        Categories = new List <Category>(),
                        Attributes = new List <Attribute>()
                    };

                    // asset classification can be copied from model
                    //
                    if (modelAsset.Categories != null)
                    {
                        reportAsset.Categories.AddRange(modelAsset.Categories);
                    }

                    var assetCachedValidator = new CachedPropertiesAndAttributesValidator <Asset>(modelAsset);
                    foreach (var req in RequirementDetails)
                    {
                        object satValue;
                        if (assetCachedValidator.CanSatisfy(req, out satValue))
                        {
                            // passes locally
                            if (!cachedValidator.AlreadySatisfies(req))
                            {
                                iAssetRequirementsMatched++;
                            }
                            var a = req.Attribute.Clone();
                            if (satValue is AttributeValue)
                            {
                                a.Value = satValue as AttributeValue;
                            }
                            else
                            {
                                a.Value = null;
                            }
                            a.Categories = new List <Category>()
                            {
                                FacilityValidator.PassedCat
                            };
                            reportAsset.Attributes.Add(a);
                        }
                        else if (!cachedValidator.AlreadySatisfies(req)) // fails locally, and is not passed at higher level, then add to explicit report fail
                        {
                            var a = req.Attribute.Clone();
                            if (satValue is AttributeValue)
                            {
                                a.Value = satValue as AttributeValue;
                            }
                            else
                            {
                                a.Value = null;
                            }
                            a.Categories = new List <Category>()
                            {
                                FacilityValidator.FailedCat
                            };
                            reportAsset.Attributes.Add(a);
                        }
                    }


                    var sb = new StringBuilder();
                    sb.AppendFormat("{0} of {1} outstanding requirements addressed at asset level.", iAssetRequirementsMatched, outstandingRequirementsCount);

                    var pass = (outstandingRequirementsCount == iAssetRequirementsMatched);
                    if (!pass)
                    {
                        anyAssetFails = true;
                        reportAsset.Categories.Add(FacilityValidator.FailedCat);
                    }
                    else
                    {
                        iPassed++;
                        reportAsset.Categories.Add(FacilityValidator.PassedCat);
                    }
                    reportAsset.Description = sb.ToString();
                    retType.Assets.Add(reportAsset);
                }
            }
            retType.Categories.Add(
                anyAssetFails ? FacilityValidator.FailedCat : FacilityValidator.PassedCat
                );

            retType.SetSubmittedAssetsCount(iSubmitted);
            retType.SetValidAssetsCount(iPassed);
            return(retType);
        }