/// <summary>
        /// This method searches through the facilities to look
        /// for properties inside the property sets of Assets
        /// to look for values that match Regex classification
        /// formats, set out in the DataReader. It then adds any
        /// values that match the Regular Expression as a category
        /// of assets which conforms with the Schema.
        /// </summary>
        private void AddClassificationsToAssets(CobieFacility facility)
        {
            var dataReader = new ClassificationMappingReader(facility.Model.Logger);//DataReader Object which will create and populate the mappings table.

            //Get Each AssetType
            foreach (var type in facility.Model.Instances.OfType <CobieType>())
            {
                //Get Each Asset
                foreach (var component in type.Components)
                {
                    //Get Each Property
                    foreach (var attribute in component.Attributes)
                    {
                        if (attribute.Value == null || component.Categories.Count != 0)
                        {
                            continue;
                        }
                        //Get the Inferred Classifications

                        var inferredClassifications = FindInferredClassifications(attribute.Value.ToString(), dataReader);

                        foreach (var ic in inferredClassifications)
                        {
                            var uniclassMatch = false;
                            var nbsMatch      = false;
                            var nrmMatch      = false;

                            foreach (var cat in component.Categories)
                            {
                                if (ic.UniclassCode != null && cat.Value == ic.UniclassCode)
                                {
                                    uniclassMatch = true;
                                }
                                if (ic.NbsCode != null && cat.Value == ic.NbsCode)
                                {
                                    nbsMatch = true;
                                }
                                if (ic.NrmCode != null && cat.Value == ic.NrmCode)
                                {
                                    nrmMatch = true;
                                }
                            }
                            //Add the Classifications as categories if they exist.
                            if (ic.UniclassCode != null && !uniclassMatch)
                            {
                                var uniClass = GetCategory(ic.UniclassCode, ic.UniclassDescription);
                                uniClass.Classification = GetClassification(Uniclass2015Name);
                                component.Categories.Add(uniClass);
                            }
                            if (ic.NbsCode != null && !nbsMatch)
                            {
                                var nbs = GetCategory(ic.NbsCode, ic.NbsDescription);
                                nbs.Classification = GetClassification(NBSReferenceName);
                                component.Categories.Add(nbs);
                            }
                            if (ic.NrmCode != null && !nrmMatch)
                            {
                                var nrm = GetCategory(ic.NrmCode, ic.NrmDescription);
                                nrm.Classification = GetClassification(NRMReferenceName);
                                component.Categories.Add(nrm);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Checks the property passed in as a parement to see
        /// if the property value matches the format of either
        /// Uniclass, NBS or NRM.
        /// </summary>
        /// <param name="property">A string value of the assets property</param>
        /// <param name="dataReader"></param>
        /// <returns>An InferredClassification which contains the classification mappings</returns>
        private static IEnumerable <InferredClassification> FindInferredClassifications(string property, ClassificationMappingReader dataReader)
        {
            //Check to see if the property is a valid classification
            Pointer match = null;
            var     classificationMatches = Regex.Match(property, RegexPatterns.UniclassPattern);

            if (classificationMatches.Success)
            {
                match = dataReader.GetMatchingPointer(classificationMatches.Value); //Get Uniclass matches from the Mappings Table
            }
            else
            {
                classificationMatches = Regex.Match(property, RegexPatterns.NbsPattern);
                if (classificationMatches.Success)
                {
                    match = dataReader.GetMatchingPointer(classificationMatches.Value);
                }
                else
                {
                    classificationMatches = Regex.Match(property, RegexPatterns.NrmPattern);
                    if (classificationMatches.Success)
                    {
                        match = dataReader.GetMatchingPointer(classificationMatches.Value);
                    }
                }
            }
            //Get Mappings that match the InferredClassification
            return(match != null?
                   dataReader.GetInferredMapping(match) :
                       Enumerable.Empty <InferredClassification>());
        }