/// <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); }