/// <summary>
        /// Gets an ontology data containing the facts which are members of this restriction
        /// </summary>
        public override RDFOntologyData EnlistMembers(RDFOntology ontology) {
            var resultFacts   = new RDFOntologyData();
            if (ontology     != null) {

                //Retrieve ontology data facts having the restricted property in their attributes
                var facts     = base.EnlistMembers(ontology);

                //Iterate the ontology data facts
                foreach(var f in facts) {

                    //Iterate the ontology attributes of the current ontology fact
                    var factOntAttributesEnum = f.OntologyAttributesEnumerator();
                    while (factOntAttributesEnum.MoveNext()) {
                        if (factOntAttributesEnum.Current.AttributeProperty.Equals(this.OnProperty)) {
                            if (factOntAttributesEnum.Current.AttributeValue.Equals(this.RequiredFact)) {
                                resultFacts.AddFact(f);
                            }
                        }
                    }

                }

            }
            return resultFacts;
        }
        /// <summary>
        /// Initializes the ontology with predefined classes and taxonomies
        /// </summary>
        internal static void InitializeOntology(RDFOntology ontology) {

            //Preload the default classes into the given ontology
            foreach (var c in RDFSemanticsUtilities.DefaultClasses) {
                if (!ontology.Model.ClassModel.Classes.ContainsKey(c.Key)) {
                    ontology.Model.ClassModel.Classes.Add(c.Key, c.Value);
                }
            }

        }
        /// <summary>
        /// Gets an ontology data containing the facts which are members of this class
        /// </summary>
        public override RDFOntologyData EnlistMembers(RDFOntology ontology) {
            var facts     = new RDFOntologyData();
            if (ontology != null) {

                //Get the facts belonging to the complemented class
                facts     = this.ComplementClass.EnlistMembers(ontology);

                //Complement the ontology data with the retrieved facts
                facts     = ontology.Data.DifferenceWith(facts);

            }
            return facts;
        }
        /// <summary>
        /// Validation rule checking usage of reserved RDF/RDFS/OWL terms in vocabulary of classes, properties and facts
        /// </summary>
        internal static void Vocabulary_Reservation(RDFOntology ontology, RDFOntologyValidationReport report) {
            RDFSemanticsEvents.RaiseSemanticsInfo("Launched execution of validation rule 'Vocabulary_Reservation'");

            #region Classes
            foreach (var  c in ontology.Model.ClassModel.Where(cls => cls.ToString().StartsWith(RDFVocabulary.RDF.BASE_URI)  ||
                                                                      cls.ToString().StartsWith(RDFVocabulary.RDFS.BASE_URI) ||
                                                                      cls.ToString().StartsWith(RDFVocabulary.OWL.BASE_URI))) {
                if (!c.Equals(RDFVocabulary.OWL.THING)       && !c.Equals(RDFVocabulary.OWL.NOTHING) &&
                    !c.Equals(RDFVocabulary.RDFS.LITERAL)    && 
                    !c.Equals(RDFVocabulary.RDF.XML_LITERAL) && !c.Equals(RDFVocabulary.RDF.HTML)) {
                     report.AddEvidence(new RDFOntologyValidationEvidence(
                         RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                         "Vocabulary_Reservation",
                         String.Format("RDF/RDFS/OWL vocabularies are reserved, they cannot be used for class names."),
                         String.Format("Remove ontology class '{0}' from the class model.", c)
                     ));
                }
            }
            #endregion

            #region Properties
            foreach (var  p in ontology.Model.PropertyModel.Where(prop => prop.ToString().StartsWith(RDFVocabulary.RDF.BASE_URI)  ||
                                                                          prop.ToString().StartsWith(RDFVocabulary.RDFS.BASE_URI) ||
                                                                          prop.ToString().StartsWith(RDFVocabulary.OWL.BASE_URI))) {
                report.AddEvidence(new RDFOntologyValidationEvidence(
                    RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                    "Vocabulary_Reservation",
                    String.Format("RDF/RDFS/OWL vocabularies are reserved, they cannot be used for property names."),
                    String.Format("Remove ontology property '{0}' from the property model.", p)
                ));
            }
            #endregion

            #region Facts
            foreach (var  f in ontology.Data.Where(fact => fact.ToString().StartsWith(RDFVocabulary.RDF.BASE_URI)  ||
                                                           fact.ToString().StartsWith(RDFVocabulary.RDFS.BASE_URI) ||
                                                           fact.ToString().StartsWith(RDFVocabulary.OWL.BASE_URI))) {
                report.AddEvidence(new RDFOntologyValidationEvidence(
                    RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                    "Vocabulary_Reservation",
                    String.Format("RDF/RDFS/OWL vocabularies are reserved, they cannot be used for fact names."),
                    String.Format("Remove ontology fact '{0}' from the data.", f)
                ));
            }
            #endregion

            RDFSemanticsEvents.RaiseSemanticsInfo("Completed execution of validation rule 'Vocabulary_Reservation'");
        }
        /// <summary>
        /// Gets an ontology data containing the facts which are direct members of this restrictions
        /// </summary>
        public override RDFOntologyData EnlistMembers(RDFOntology ontology) {
            var facts     = new RDFOntologyData();
            if (ontology != null) {

                //Iterate the ontology data facts
                foreach(RDFOntologyFact f in ontology.Data) {

                    //Iterate the ontology attributes of the current ontology fact
                    var factOntAttributesEnum = f.OntologyAttributesEnumerator();
                    while (factOntAttributesEnum.MoveNext()) {
                        if (factOntAttributesEnum.Current.AttributeProperty.Equals(this.OnProperty)) {
                            facts.AddFact(f);
                        }
                    }

                }

            }
            return facts;
        }
        /// <summary>
        /// Applies the reasoner on the given ontology, producing a reasoning report.
        /// </summary>
        public RDFOntologyReasonerReport ApplyToOntology(ref RDFOntology ontology)
        {
            if (ontology != null)
            {
                var report = new RDFOntologyReasonerReport();
                RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Reasoner is going to be applied on Ontology '{0}'", ontology.Value));

                //Expand ontology
                ontology = ontology.UnionWith(RDFBASEOntology.Instance);

                #region Triggers
                //Apply first rules
                this.TriggerRule("EquivalentClassTransitivity", ontology, report);
                this.TriggerRule("SubClassTransitivity", ontology, report);
                this.TriggerRule("DisjointWithEntailment", ontology, report);
                this.TriggerRule("EquivalentPropertyTransitivity", ontology, report);
                this.TriggerRule("SubPropertyTransitivity", ontology, report);
                this.TriggerRule("SameAsTransitivity", ontology, report);
                this.TriggerRule("DifferentFromEntailment", ontology, report);

                //Apply second rules
                this.TriggerRule("DomainEntailment", ontology, report);
                this.TriggerRule("RangeEntailment", ontology, report);
                this.TriggerRule("ClassTypeEntailment", ontology, report);
                this.TriggerRule("InverseOfEntailment", ontology, report);
                this.TriggerRule("SymmetricPropertyEntailment", ontology, report);
                this.TriggerRule("TransitivePropertyEntailment", ontology, report);
                this.TriggerRule("PropertyEntailment", ontology, report);
                this.TriggerRule("SameAsEntailment", ontology, report);
                #endregion

                //Unexpand ontology
                ontology = ontology.DifferenceWith(RDFBASEOntology.Instance);

                RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Reasoner has been applied on Ontology '{0}'", ontology.Value));
                return(report);
            }
            throw new RDFSemanticsException("Cannot apply RDFOntologyReasoner because given \"ontology\" parameter is null.");
        }
        /// <summary>
        /// Validation rule checking for consistency of owl:inverseOf axioms
        /// </summary>
        internal static void InverseOf(RDFOntology ontology, RDFOntologyValidationReport report) {
            RDFSemanticsEvents.RaiseSemanticsInfo("Launched execution of validation rule 'InverseOf'");

            #region InverseOf
            foreach (var invOf in ontology.Model.PropertyModel.Relations.InverseOf) {

                #region Domain VS Range
                if (((RDFOntologyObjectProperty)invOf.TaxonomySubject).Domain != null  &&
                    ((RDFOntologyObjectProperty)invOf.TaxonomyObject).Range   != null)  {
                      if (!RDFOntologyReasoningHelper.IsRangeClassOf(((RDFOntologyObjectProperty)invOf.TaxonomySubject).Domain, 
                                                                     (RDFOntologyObjectProperty)invOf.TaxonomyObject, 
                                                                      ontology.Model.ClassModel)) {
                           report.AddEvidence(new RDFOntologyValidationEvidence(
                               RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                               "InverseOf",
                               String.Format("Violation of 'rdfs:domain' constraint on 'owl:inverseOf' taxonomy between property '{0}' and property '{1}'.", invOf.TaxonomySubject, invOf.TaxonomyObject),
                               String.Format("Review 'rdfs:domain' constraint on ontology property '{0}' in order to be compatible with 'rdfs:range' constraint on ontology property '{1}'.", invOf.TaxonomySubject, invOf.TaxonomyObject)
                           ));
                      }
                }
                #endregion

                #region Range VS Domain
                if (((RDFOntologyObjectProperty)invOf.TaxonomySubject).Range != null  &&
                    ((RDFOntologyObjectProperty)invOf.TaxonomyObject).Domain != null)  {
                      if (!RDFOntologyReasoningHelper.IsDomainClassOf(((RDFOntologyObjectProperty)invOf.TaxonomySubject).Range, 
                                                                      (RDFOntologyObjectProperty)invOf.TaxonomyObject, 
                                                                       ontology.Model.ClassModel)) {
                           report.AddEvidence(new RDFOntologyValidationEvidence(
                               RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                               "InverseOf",
                               String.Format("Violation of 'rdfs:range' constraint on 'owl:inverseOf' taxonomy between property '{0}' and property '{1}'.", invOf.TaxonomySubject, invOf.TaxonomyObject),
                               String.Format("Review 'rdfs:range' constraint on ontology property '{0}' in order to be compatible with 'rdfs:domain' constraint on ontology property '{1}'.", invOf.TaxonomySubject, invOf.TaxonomyObject)
                           ));
                      }
                }
                #endregion

            }
            #endregion

            RDFSemanticsEvents.RaiseSemanticsInfo("Completed execution of validation rule 'InverseOf'");
        }
        /// <summary>
        /// Validation rule checking for consistency of owl:SymmetricProperty axioms
        /// </summary>
        internal static void SymmetricProperty(RDFOntology ontology, RDFOntologyValidationReport report) {
            RDFSemanticsEvents.RaiseSemanticsInfo("Launched execution of validation rule 'SymmetricProperty'");

            #region SymmetricProperty
            foreach(var symProp in ontology.Model.PropertyModel.Where(prop => prop.IsSymmetricProperty() && (prop.Domain != null || prop.Range != null))) {
                foreach(var asn in ontology.Data.Relations.Assertions.Where(asn => asn.TaxonomyPredicate.Equals(symProp))) {

                    #region Domain
                    if(symProp.Domain != null) {
                       if(!RDFOntologyReasoningHelper.IsMemberOf((RDFOntologyFact)asn.TaxonomyObject, symProp.Domain, ontology)) {
                           report.AddEvidence(new RDFOntologyValidationEvidence(
                               RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                               "SymmetricProperty",
                               String.Format("Violation of 'owl:SymmetricProperty' constraint on property '{0}': range fact '{1}' is not compatible with domain class '{2}' of the property.", symProp, asn.TaxonomyObject, symProp.Domain),
                               String.Format("Review classtypes of ontology fact '{0}' in order to be compatible with 'rdfs:domain' constraint on ontology property '{1}'.", asn.TaxonomyObject, symProp)
                           ));
                        }
                    }
                    #endregion

                    #region Range
                    if(symProp.Range  != null) {
                        if(!RDFOntologyReasoningHelper.IsMemberOf((RDFOntologyFact)asn.TaxonomySubject, symProp.Range, ontology)) {
                            report.AddEvidence(new RDFOntologyValidationEvidence(
                                RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                "SymmetricProperty",
                                String.Format("Violation of 'owl:SymmetricProperty' constraint on property '{0}': domain fact '{1}' is not compatible with range class '{2}' of the property.", symProp, asn.TaxonomySubject, symProp.Range),
                                String.Format("Review classtypes of ontology fact '{0}' in order to be compatible with 'rdfs:range' constraint on ontology property '{1}'.", asn.TaxonomySubject, symProp)
                            ));
                        }
                    }
                    #endregion

                }

            }
            #endregion

            RDFSemanticsEvents.RaiseSemanticsInfo("Completed execution of validation rule 'SymmetricProperty'");
        }
        /// <summary>
        /// Loads the restrictions from the given graph into the given ontology
        /// </summary>
        internal static void LoadRestrictions(RDFGraph ontGraph, RDFOntology ontology, RDFGraph rdfType) {
            foreach (var t in rdfType.SelectTriplesByObject(RDFVocabulary.OWL.RESTRICTION)) {

                #region onProperty
                var p = ontGraph.SelectTriplesBySubject((RDFResource)t.Subject)
                                .SelectTriplesByPredicate(RDFVocabulary.OWL.ON_PROPERTY)
                                .FirstOrDefault();
                if (p != null) {
                    var onProp  = ontology.Model.PropertyModel.SelectProperty(p.Object.ToString());
                    if (onProp != null) {
                        var ontRestr             = new RDFOntologyRestriction(onProp);
                        ontRestr.Value           = t.Subject;
                        ontRestr.PatternMemberID = t.Subject.PatternMemberID;
                        ontology.Model.ClassModel.AddRestriction(ontRestr);
                    }
                    else {
                        throw new RDFSemanticsException("Cannot load restriction '" + t.Subject + "' from graph, because its applied property '" + p.Object + "' has not been found in the ontology model.");
                    }
                }
                #endregion

            }
        }
        /// <summary>
        /// Loads the enumerate classes from the griven graph into the given ontology
        /// </summary>
        internal static void LoadEnumerates(RDFGraph ontGraph, RDFOntology ontology) {
            var changeLog = new Dictionary<Int64, RDFOntologyClass>();
            foreach (var c in ontology.Model.ClassModel) {

                #region Enumerate
                var onOf  = ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                    .SelectTriplesByPredicate(RDFVocabulary.OWL.ONE_OF)
                                    .FirstOrDefault();
                if (onOf != null) {
                    var nilFound        = false;
                    var itemRest        = (RDFResource)onOf.Object;
                    while (!nilFound) {

                        #region rdf:first
                        var first       = ontGraph.SelectTriplesBySubject(itemRest)
                                                  .SelectTriplesByPredicate(RDFVocabulary.RDF.FIRST)
                                                  .FirstOrDefault();
                        if (first != null) {
                            var enMemb  = ontology.Data.SelectFact(first.Object.ToString());
                            if (enMemb != null) {
                                if (!changeLog.ContainsKey(c.PatternMemberID)) {
                                    var ontEClass             = new RDFOntologyEnumerateClass(enMemb.IsObjectFact() ?
                                                                    RDFSemanticsEnums.RDFOntologyEnumerateClassCategory.ResourceEnumeration :
                                                                    RDFSemanticsEnums.RDFOntologyEnumerateClassCategory.LiteralEnumeration);
                                    ontEClass.Value           = c.Value;
                                    ontEClass.PatternMemberID = c.PatternMemberID;
                                    ontEClass.AddEnumerateMember(enMemb);
                                    changeLog.Add(c.PatternMemberID, ontEClass);
                                }
                                else {
                                    if ((((RDFOntologyEnumerateClass)changeLog[c.PatternMemberID]).Category  == RDFSemanticsEnums.RDFOntologyEnumerateClassCategory.ResourceEnumeration && enMemb.IsObjectFact()) ||
                                         (((RDFOntologyEnumerateClass)changeLog[c.PatternMemberID]).Category == RDFSemanticsEnums.RDFOntologyEnumerateClassCategory.LiteralEnumeration  && enMemb.IsLiteralFact())) {
                                        ((RDFOntologyEnumerateClass)changeLog[c.PatternMemberID]).AddEnumerateMember(enMemb);
                                    }
                                }
                            }
                            else {
                                throw new RDFSemanticsException("Cannot load enumerate class '" + c.Value + "' from graph, because its enumerate fact member '" + first.Object + "' has not been found in the ontology data.");
                            }

                            #region rdf:rest
                            var rest    = ontGraph.SelectTriplesBySubject(itemRest)
                                                  .SelectTriplesByPredicate(RDFVocabulary.RDF.REST)
                                                  .FirstOrDefault();
                            if (rest != null) {
                                if (rest.Object.Equals(RDFVocabulary.RDF.NIL)) {
                                    nilFound = true;
                                }
                                else {
                                    itemRest = (RDFResource)rest.Object;
                                }
                            }
                            #endregion

                        }
                        #endregion

                    }
                }
                #endregion

            }
            foreach (var cl in changeLog) {
                ontology.Model.ClassModel.Classes[cl.Key] = cl.Value;
            }
        }
        /// <summary>
        /// Validation rule checking for usage of deprecated classes and properties
        /// </summary>
        internal static void Deprecation(RDFOntology ontology, RDFOntologyValidationReport report) {
            RDFSemanticsEvents.RaiseSemanticsInfo("Launched execution of validation rule 'Deprecation'");

            #region Class
            foreach (var deprCls   in ontology.Data.Relations.ClassType.Where(c => c.TaxonomyObject.IsDeprecatedClass())) {
                report.AddEvidence(new RDFOntologyValidationEvidence(
                    RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                    "Deprecation",
                    String.Format("Ontology fact '{0}' has a classtype '{1}', which is deprecated (may be removed in a future ontology version!).", deprCls.TaxonomySubject, deprCls.TaxonomyObject),
                    String.Format("Update the classtype of ontology fact '{0}' to a non-deprecated class definition.", deprCls.TaxonomySubject)
                ));
            }
            #endregion

            #region Property
            foreach (var deprProp  in ontology.Data.Relations.Assertions.Where(p => p.TaxonomyPredicate.IsDeprecatedProperty())) {
                report.AddEvidence(new RDFOntologyValidationEvidence(
                    RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                    "Deprecation",
                    String.Format("Ontology fact '{0}' has an assertion using ontology property '{1}', which is deprecated (may be removed in a future ontology version!).", deprProp.TaxonomySubject, deprProp.TaxonomyPredicate),
                    String.Format("Update the assertion of ontology fact '{0}' to a non-deprecated property definition.", deprProp.TaxonomySubject)
                ));
            }
            #endregion

            RDFSemanticsEvents.RaiseSemanticsInfo("Completed execution of validation rule 'Deprecation'");
        }
        /// <summary>
        /// Default-ctor to initialize the BASE ontology
        /// </summary>
        static RDFBASEOntology()
        {
            #region Declarations

            #region Ontology
            Instance = new RDFOntology(new RDFResource("https://rdfsharpsemantics.codeplex.com/base_ontology#"), true);
            #endregion

            #region Classes

            //RDF+RDFS
            Instance.Model.ClassModel.AddClass(RDFVocabulary.RDFS.RESOURCE.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.RDFS.CLASS.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.RDFS.LITERAL.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.RDF.XML_LITERAL.ToRDFOntologyClass());

            //XSD
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.ANY_URI.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.BASE64_BINARY.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.BOOLEAN.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.BYTE.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.DATE.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.DATETIME.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.DECIMAL.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.DOUBLE.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.DURATION.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.FLOAT.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.G_DAY.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.G_MONTH.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.G_MONTH_DAY.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.G_YEAR.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.G_YEAR_MONTH.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.HEX_BINARY.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.INT.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.INTEGER.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.LANGUAGE.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.LONG.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.NAME.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.NCNAME.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.NEGATIVE_INTEGER.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.NMTOKEN.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.NON_NEGATIVE_INTEGER.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.NON_POSITIVE_INTEGER.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.NORMALIZED_STRING.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.NOTATION.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.POSITIVE_INTEGER.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.QNAME.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.SHORT.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.STRING.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.TIME.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.TOKEN.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.UNSIGNED_BYTE.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.UNSIGNED_INT.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.UNSIGNED_LONG.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.XSD.UNSIGNED_SHORT.ToRDFOntologyClass());

            //OWL
            Instance.Model.ClassModel.AddClass(RDFVocabulary.OWL.THING.ToRDFOntologyClass());
            Instance.Model.ClassModel.AddClass(RDFVocabulary.OWL.NOTHING.ToRDFOntologyClass());

            #endregion

            #region Properties

            //RDF+RDFS
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.RDF.TYPE.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.RDFS.SUB_CLASS_OF.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.RDFS.SUB_PROPERTY_OF.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.RDFS.DOMAIN.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.RDFS.RANGE.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.RDFS.COMMENT.ToRDFOntologyAnnotationProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.RDFS.LABEL.ToRDFOntologyAnnotationProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.RDFS.SEE_ALSO.ToRDFOntologyAnnotationProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.RDFS.IS_DEFINED_BY.ToRDFOntologyAnnotationProperty());

            //OWL
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.EQUIVALENT_CLASS.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.DISJOINT_WITH.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.EQUIVALENT_PROPERTY.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.INVERSE_OF.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.ON_PROPERTY.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.ONE_OF.ToRDFOntologyProperty()); //plain property
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.UNION_OF.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.INTERSECTION_OF.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.COMPLEMENT_OF.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.ALL_VALUES_FROM.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.SOME_VALUES_FROM.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.HAS_VALUE.ToRDFOntologyProperty()); //plain property
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.SAME_AS.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.DIFFERENT_FROM.ToRDFOntologyObjectProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.CARDINALITY.ToRDFOntologyDatatypeProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.MIN_CARDINALITY.ToRDFOntologyDatatypeProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.MAX_CARDINALITY.ToRDFOntologyDatatypeProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.VERSION_INFO.ToRDFOntologyAnnotationProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.VERSION_IRI.ToRDFOntologyAnnotationProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.IMPORTS.ToRDFOntologyAnnotationProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.BACKWARD_COMPATIBLE_WITH.ToRDFOntologyAnnotationProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.INCOMPATIBLE_WITH.ToRDFOntologyAnnotationProperty());
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.OWL.PRIOR_VERSION.ToRDFOntologyAnnotationProperty());

            //VS
            Instance.Model.PropertyModel.AddProperty(RDFVocabulary.VS.TERM_STATUS.ToRDFOntologyAnnotationProperty());

            #endregion

            #endregion

            #region Taxonomies

            #region ClassModel

            //SubClassOf
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDF.XML_LITERAL.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.STRING.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.BOOLEAN.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.BASE64_BINARY.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.HEX_BINARY.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.FLOAT.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DECIMAL.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DOUBLE.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.ANY_URI.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.QNAME.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NOTATION.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DURATION.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DATETIME.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.RDFS.LITERAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.TIME.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DATETIME.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DATE.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DATETIME.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.G_YEAR_MONTH.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DATE.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.G_YEAR.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DATE.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.G_MONTH_DAY.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DATE.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.G_DAY.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DATE.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.G_MONTH.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DATE.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NORMALIZED_STRING.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.STRING.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.TOKEN.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NORMALIZED_STRING.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.LANGUAGE.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.TOKEN.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NAME.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.TOKEN.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NMTOKEN.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.TOKEN.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NCNAME.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NAME.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.INTEGER.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.DECIMAL.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NON_POSITIVE_INTEGER.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.INTEGER.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NON_NEGATIVE_INTEGER.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.INTEGER.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.LONG.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.INTEGER.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NEGATIVE_INTEGER.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NON_POSITIVE_INTEGER.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.INT.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.LONG.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.SHORT.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.INT.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.BYTE.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.SHORT.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.POSITIVE_INTEGER.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NON_NEGATIVE_INTEGER.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.UNSIGNED_LONG.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.NON_NEGATIVE_INTEGER.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.UNSIGNED_INT.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.UNSIGNED_LONG.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.UNSIGNED_SHORT.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.UNSIGNED_INT.ToString()));
            Instance.Model.ClassModel.AddSubClassOfRelation(Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.UNSIGNED_BYTE.ToString()), Instance.Model.ClassModel.SelectClass(RDFVocabulary.XSD.UNSIGNED_SHORT.ToString()));

            #endregion

            #endregion
        }
        /// <summary>
        /// Analyzes the given ontology and produces a detailed report of found evidences
        /// </summary>
        internal RDFOntologyValidationReport AnalyzeOntology(RDFOntology ontology) {
            var report = new RDFOntologyValidationReport(ontology.Value.PatternMemberID);

            //Execute the validation rules
            Parallel.ForEach(this.Rules, rule => {
                rule.ExecuteRule(ontology, report);
            });

            return report;
        }
        /// <summary>
        /// Validation rule checking consistency of local cardinality constraints
        /// </summary>
        internal static void LocalCardinalityConstraint(RDFOntology ontology, RDFOntologyValidationReport report) {
            RDFSemanticsEvents.RaiseSemanticsInfo("Launched execution of validation rule 'LocalCardinalityConstraint'");

            #region LocalCardinalityConstraint
            //OWL-DL requires that for a transitive property no local cardinality constraints should
            //be declared on the property itself, or its super properties, or its inverse properties.
            foreach (var cardRestr in ontology.Model.ClassModel.Where(c => c is RDFOntologyCardinalityRestriction).OfType<RDFOntologyCardinalityRestriction>()) {
                var  restrProp      = ontology.Model.PropertyModel.SelectProperty(cardRestr.OnProperty.ToString());
                if  (restrProp     != null) {
                    if (restrProp.IsObjectProperty()) {
                        if (((RDFOntologyObjectProperty)restrProp).Transitive) {
                              report.AddEvidence(new RDFOntologyValidationEvidence(
                                  RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                  "LocalCardinalityConstraint",
                                  String.Format("Ontology property '{0}' is an 'owl:TransitiveProperty', but it has a local cardinality constraint '{1}'. This is not permitted in OWL-DL.", restrProp, cardRestr),
                                  String.Format("Unset the ontology property '{0}' as 'owl:TransitiveProperty', or remove the local cardinality constraint '{1}' applied on it.", restrProp, cardRestr)
                              ));
                        }
                        foreach (var subProps in RDFOntologyReasoningHelper.EnlistSubPropertiesOf(restrProp, ontology.Model.PropertyModel)) {
                            if  (subProps.IsObjectProperty()) {
                                 if (((RDFOntologyObjectProperty)subProps).Transitive) {
                                       report.AddEvidence(new RDFOntologyValidationEvidence(
                                           RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                           "LocalCardinalityConstraint",
                                           String.Format("Ontology property '{0}' has a local cardinality constraint '{1}', but it is also super property of ontology property '{2}', which is an 'owl:TransitiveProperty'. This is not permitted in OWL-DL.", restrProp, cardRestr, subProps),
                                           String.Format("Unset the ontology property '{0}' as 'owl:TransitiveProperty', or remove the local cardinality constraint '{1}' applied on its super property '{2}'.", subProps, cardRestr, restrProp)
                                       ));
                                 }
                            }
                        }
                        foreach (var inverseProps in ontology.Model.PropertyModel.Relations.InverseOf.SelectEntriesBySubject(restrProp)) {
                            if  (((RDFOntologyObjectProperty)inverseProps.TaxonomyObject).Transitive) {
                                   report.AddEvidence(new RDFOntologyValidationEvidence(
                                       RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                       "LocalCardinalityConstraint",
                                       String.Format("Ontology property '{0}' has a local cardinality constraint '{1}', but it also has an 'owl:inverseOf' relation with ontology property '{2}', which is an 'owl:TransitiveProperty'. This is not permitted in OWL-DL.", restrProp, cardRestr, inverseProps.TaxonomyObject),
                                       String.Format("Unset the ontology property '{0}' as 'owl:TransitiveProperty', or remove the local cardinality constraint '{1}' applied on its inverse ontology property '{2}'.", inverseProps.TaxonomyObject, cardRestr, restrProp)
                                   ));
                            }
                        }
                    }
                }
            }
            #endregion

            RDFSemanticsEvents.RaiseSemanticsInfo("Completed execution of validation rule 'LocalCardinalityConstraint'");
        }
        /// <summary>
        /// Enlists the facts which are members of the given class within the given ontology
        /// </summary>
        public static RDFOntologyData EnlistMembersOf(RDFOntologyClass ontClass, RDFOntology ontology) {
            var result      = new RDFOntologyData();
            if (ontClass   != null && ontology != null) {
                
                //Restriction
                if (ontClass.IsRestrictionClass()) {
                    result  = RDFSemanticsUtilities.EnlistMembersOfRestriction((RDFOntologyRestriction)ontClass,  ontology);
                }

                //Enumeration
                else if (ontClass.IsEnumerateClass()) {
                    result  = RDFSemanticsUtilities.EnlistMembersOfEnumerate((RDFOntologyEnumerateClass)ontClass, ontology);
                }

                //DataRange
                else if (ontClass.IsDataRangeClass()) {
                    result  = RDFSemanticsUtilities.EnlistMembersOfDataRange((RDFOntologyDataRangeClass)ontClass, ontology);
                }

                //Composite
                else if (ontClass.IsCompositeClass()) {
                    result  = RDFSemanticsUtilities.EnlistMembersOfComposite(ontClass, ontology);
                }

                //SimpleClass
                else {
                    result  = RDFSemanticsUtilities.EnlistMembersOfClass(ontClass, ontology);
                }

            }
            return result;
        }
        /// <summary>
        /// Gets an ontology data containing the facts which are members of this class
        /// </summary>
        public override RDFOntologyData EnlistMembers(RDFOntology ontology) {
            var facts            = new RDFOntologyData();
            if (ontology        != null) {

                //Iterate the enumerate members and check if they are contained in the ontology data
                var enumMembers  = this.EnumerateMembersEnumerator();
                while (enumMembers.MoveNext()) {
                    var ontFact  = ontology.Data.SelectFact(enumMembers.Current.ToString());
                    if (ontFact != null) {
                        facts.AddFact(ontFact);
                    }
                }

            }
            return facts;
        }
 /// <summary>
 /// Checks if the given fact is member of the given class within the given ontology
 /// </summary>
 public static Boolean IsMemberOf(RDFOntologyFact ontFact, RDFOntologyClass ontClass, RDFOntology ontology) { 
     return(ontFact != null && ontClass != null && ontology != null ? RDFOntologyReasoningHelper.EnlistMembersOf(ontClass, ontology).Facts.ContainsKey(ontFact.PatternMemberID) : false);
 }
 /// <summary>
 /// Loads the annotation properties from the given graph into the given ontology
 /// </summary>
 internal static void LoadAnnotationProperties(RDFGraph ontGraph, RDFOntology ontology, RDFGraph customAnnot) {
     foreach (var t in customAnnot) {
         var anProp  = new RDFOntologyAnnotationProperty((RDFResource)t.Subject);
         ontology.Model.PropertyModel.AddProperty(anProp);
     }
 }
        /// <summary>
        /// Updates the previously detected restrictions to their specific types
        /// </summary>
        internal static void RefineRestrictions(RDFGraph ontGraph, RDFOntology ontology) {
            var changeLog      = new Dictionary<Int64, RDFOntologyClass>();
            foreach (var c in ontology.Model.ClassModel) {
                if (c.IsRestrictionClass()) {

                    #region CardinalityRestriction
                    Int32 minC = 0;
                    var crMin  = ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                         .SelectTriplesByPredicate(RDFVocabulary.OWL.MIN_CARDINALITY)
                                         .FirstOrDefault();
                    if (crMin != null && crMin.TripleFlavor == RDFModelEnums.RDFTripleFlavors.SPL) {
                        if (crMin.Object is RDFPlainLiteral) {
                            if (Regex.IsMatch(crMin.Object.ToString(), @"^[0-9]+$")) {
                                minC = Int32.Parse(crMin.Object.ToString());
                            }
                        }
                        else {
                            if (((RDFTypedLiteral)crMin.Object).Datatype.Category == RDFModelEnums.RDFDatatypeCategory.Numeric) {
                                if (Regex.IsMatch(((RDFTypedLiteral)crMin.Object).Value, @"^[0-9]+$")) {
                                    minC = Int32.Parse(((RDFTypedLiteral)crMin.Object).Value);
                                }
                            }
                        }
                    }

                    Int32 maxC = 0;
                    var crMax  = ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                         .SelectTriplesByPredicate(RDFVocabulary.OWL.MAX_CARDINALITY)
                                         .FirstOrDefault();
                    if (crMax != null && crMax.TripleFlavor == RDFModelEnums.RDFTripleFlavors.SPL) {
                        if (crMax.Object is RDFPlainLiteral) {
                            if (Regex.IsMatch(crMax.Object.ToString(), @"^[0-9]+$")) {
                                maxC = Int32.Parse(crMax.Object.ToString());
                            }
                        }
                        else {
                            if (((RDFTypedLiteral)crMax.Object).Datatype.Category == RDFModelEnums.RDFDatatypeCategory.Numeric) {
                                if (Regex.IsMatch(((RDFTypedLiteral)crMax.Object).Value, @"^[0-9]+$")) {
                                    maxC = Int32.Parse(((RDFTypedLiteral)crMax.Object).Value);
                                }
                            }
                        }
                    }

                    if ((minC > 0 || maxC > 0) && !changeLog.ContainsKey(c.PatternMemberID)) {
                        var restr                = new RDFOntologyCardinalityRestriction(((RDFOntologyRestriction)c).OnProperty, minC, maxC);
                        restr.Value              = c.Value;
                        restr.PatternMemberID    = c.PatternMemberID;
                        restr.DirectSubClasses   = c.DirectSubClasses;
                        restr.DirectSuperClasses = c.DirectSuperClasses;
                        restr.DisjointClasses    = c.DisjointClasses;
                        restr.EquivalentClasses  = c.EquivalentClasses;
                        changeLog.Add(restr.PatternMemberID, restr);
                    }
                    #endregion

                    #region HasValueRestriction
                    var hvRes      = ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                             .SelectTriplesByPredicate(RDFVocabulary.OWL.HAS_VALUE)
                                             .FirstOrDefault();
                    if (hvRes     != null) {
                        var hvFct  = ontology.Data.SelectFact(hvRes.Object.ToString());
                        if (hvFct != null) {
                            if (!changeLog.ContainsKey(c.PatternMemberID)) {
                                var restr                = new RDFOntologyHasValueRestriction(((RDFOntologyRestriction)c).OnProperty, hvFct);
                                restr.Value              = c.Value;
                                restr.PatternMemberID    = c.PatternMemberID;
                                restr.DirectSubClasses   = c.DirectSubClasses;
                                restr.DirectSuperClasses = c.DirectSuperClasses;
                                restr.DisjointClasses    = c.DisjointClasses;
                                restr.EquivalentClasses  = c.EquivalentClasses;
                                changeLog.Add(restr.PatternMemberID, restr);
                            }
                        }
                        else {
                            throw new RDFSemanticsException("Cannot create hasValue restriction '" + c.Value + "' from graph, because its required fact '" + hvRes.Object + "' has not been found in the ontology data.");
                        }
                    }
                    #endregion

                    #region ValuesFromRestriction
                    var avfRes      = ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                              .SelectTriplesByPredicate(RDFVocabulary.OWL.ALL_VALUES_FROM)
                                              .FirstOrDefault();
                    if (avfRes     != null) {
                        var avfCls  = ontology.Model.ClassModel.SelectClass(avfRes.Object.ToString());
                        if (avfCls != null) {
                            if (!changeLog.ContainsKey(c.PatternMemberID)) {
                                var restr                = new RDFOntologyValuesFromRestriction(((RDFOntologyRestriction)c).OnProperty, RDFSemanticsEnums.RDFOntologyValuesFromRestrictionCategory.AllValuesFrom, avfCls);
                                restr.Value              = c.Value;
                                restr.PatternMemberID    = c.PatternMemberID;
                                restr.DirectSubClasses   = c.DirectSubClasses;
                                restr.DirectSuperClasses = c.DirectSuperClasses;
                                restr.DisjointClasses    = c.DisjointClasses;
                                restr.EquivalentClasses  = c.EquivalentClasses;
                                changeLog.Add(restr.PatternMemberID, restr);
                            }
                        }
                        else {
                            throw new RDFSemanticsException("Cannot create allValuesFrom restriction '" + c.Value + "' from graph, because its fromClass '" + avfRes.Object + "' has not been found in the ontology model.");
                        }
                    }

                    var svfRes      = ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                              .SelectTriplesByPredicate(RDFVocabulary.OWL.SOME_VALUES_FROM)
                                              .FirstOrDefault();
                    if (svfRes     != null) {
                        var svfCls  = ontology.Model.ClassModel.SelectClass(svfRes.Object.ToString());
                        if (svfCls != null) {
                            if (!changeLog.ContainsKey(c.PatternMemberID)) {
                                var restr                = new RDFOntologyValuesFromRestriction(((RDFOntologyRestriction)c).OnProperty, RDFSemanticsEnums.RDFOntologyValuesFromRestrictionCategory.SomeValuesFrom, svfCls);
                                restr.Value              = c.Value;
                                restr.PatternMemberID    = c.PatternMemberID;
                                restr.DirectSubClasses   = c.DirectSubClasses;
                                restr.DirectSuperClasses = c.DirectSuperClasses;
                                restr.DisjointClasses    = c.DisjointClasses;
                                restr.EquivalentClasses  = c.EquivalentClasses;
                                changeLog.Add(restr.PatternMemberID, restr);
                            }
                        }
                        else {
                            throw new RDFSemanticsException("Cannot create someValuesFrom restriction '" + c.Value + "' from graph, because its fromClass '" + svfRes.Object + "' has not been found in the ontology model.");
                        }
                    }
                    #endregion

                }
            }
            foreach (var cl in changeLog) {
                ontology.Model.ClassModel.Classes[cl.Key] = cl.Value;
            }
        }
        /// <summary>
        /// Validation rule checking for consistency of rdf:type axioms
        /// </summary>
        internal static void ClassType(RDFOntology ontology, RDFOntologyValidationReport report) {
            RDFSemanticsEvents.RaiseSemanticsInfo("Launched execution of validation rule 'ClassType'");
            
            #region Facts
            var disjWithCache       = new Dictionary<Int64, RDFOntologyClassModel>();
            var litCheckCache       = new Dictionary<Int64, Boolean>();
            foreach (var  fact     in ontology.Data) {
                var classTypes      = new RDFOntologyClassModel();
                foreach (var cType in ontology.Data.Relations.ClassType.SelectEntriesBySubject(fact)) {

                    //ClassTypes of a fact cannot be compatible with "rdfs:Literal"
                    var cTypeClass  = ontology.Model.ClassModel.SelectClass(cType.TaxonomyObject.ToString());
                    if (cTypeClass != null) {
                        if (!litCheckCache.ContainsKey(cTypeClass.PatternMemberID)) {
                             litCheckCache.Add(cTypeClass.PatternMemberID, RDFOntologyReasoningHelper.IsLiteralCompatibleClass(cTypeClass, ontology.Model.ClassModel));
                        }
                        if (litCheckCache[cTypeClass.PatternMemberID]) {
                            report.AddEvidence(new RDFOntologyValidationEvidence(
                                RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                "ClassType",
                                String.Format("Ontology fact '{0}' has a classtype '{1}' which is compatible with 'rdfs:Literal' and this cannot be possible.", fact, cTypeClass),
                                String.Format("Review classtypes of ontology fact '{0}'.", fact)
                            ));
                        }
                        else {
                            classTypes.AddClass(cTypeClass);
                        }
                    }

                }

                //ClassTypes of a fact cannot be disjoint
                foreach (var cType in classTypes) {
                    if  (!disjWithCache.ContainsKey(cType.PatternMemberID)) {
                          disjWithCache.Add(cType.PatternMemberID, RDFOntologyReasoningHelper.EnlistDisjointClassesWith(cType, ontology.Model.ClassModel));
                    }
                    foreach (var disjWithCType in disjWithCache[cType.PatternMemberID].IntersectWith(classTypes)) {
                        report.AddEvidence(new RDFOntologyValidationEvidence(
                            RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                            "ClassType",
                            String.Format("Ontology fact '{0}' has both classtypes '{1}' and '{2}', which cannot be compatible because of an 'owl:disjointWith' constraint.", fact, cType, disjWithCType),
                            String.Format("Review classtypes of ontology fact '{0}'.", fact)
                        ));
                    }
                }

            }
            #endregion

            RDFSemanticsEvents.RaiseSemanticsInfo("Completed execution of validation rule 'ClassType'");
        }
        /// <summary>
        /// Gets an ontology data containing the facts which are members of this class
        /// </summary>
        public override RDFOntologyData EnlistMembers(RDFOntology ontology) {
            var facts             = new RDFOntologyData();
            if (ontology         != null) {

                //Iterate the classes belonging to the intersection class
                Boolean firstIter = true;
                var compClassEnum = this.CompositingClassesEnumerator();
                while (compClassEnum.MoveNext()) {

                    //The first iteration must give the facts belonging to the first class
                    if (firstIter) {
                        facts     = compClassEnum.Current.EnlistMembers(ontology);
                        firstIter = false;
                    }

                    //The other iterations must compose them with an intersection logic
                    else {
                        facts     = facts.IntersectWith(compClassEnum.Current.EnlistMembers(ontology));
                    }

                }

            }
            return facts;
        }
        /// <summary>
        /// Validation rule checking consistency of global cardinality constraints
        /// </summary>
        internal static void GlobalCardinalityConstraint(RDFOntology ontology, RDFOntologyValidationReport report) {
            RDFSemanticsEvents.RaiseSemanticsInfo("Launched execution of validation rule 'GlobalCardinalityConstraint'");

            #region GlobalCardinalityConstraint
            foreach (var prop    in ontology.Model.PropertyModel.Where(p => p.Functional || (p.IsObjectProperty() && ((RDFOntologyObjectProperty)p).InverseFunctional))) {
                var assertions    = ontology.Data.Relations.Assertions.SelectEntriesByPredicate(prop);
                var subjCache     = new Dictionary<Int64, RDFOntologyResource>();
                var objCache      = new Dictionary<Int64, RDFOntologyResource>();

                foreach (var asn in assertions) {

                    #region Functional
                    if  (prop.IsFunctionalProperty()) {

                         if (!subjCache.ContainsKey(asn.TaxonomySubject.PatternMemberID)) {
                              subjCache.Add(asn.TaxonomySubject.PatternMemberID, asn.TaxonomySubject);
                         }
                         else {

                              //FunctionalProperty can only occur once per subject fact within assertions
                              report.AddEvidence(new RDFOntologyValidationEvidence(
                                  RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                  "GlobalCardinalityConstraint",
                                  String.Format("Ontology property '{0}' has an 'owl:FunctionalProperty' global cardinality constraint, which is violated by subject ontology fact '{1}'.", asn.TaxonomyPredicate, asn.TaxonomySubject),
                                  String.Format("Remove the '{0} {1} {2}' assertion from the data.", asn.TaxonomySubject, asn.TaxonomyPredicate, asn.TaxonomyObject)
                              ));

                         }

                         //FunctionalProperty cannot be TransitiveProperty (even indirectly)
                         if (prop.IsTransitiveProperty() || RDFOntologyReasoningHelper.EnlistSuperPropertiesOf(prop, ontology.Model.PropertyModel).Any(p => p.IsTransitiveProperty())) {
                             report.AddEvidence(new RDFOntologyValidationEvidence(
                                 RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                 "GlobalCardinalityConstraint",
                                 String.Format("Ontology property '{0}' has an 'owl:FunctionalProperty' global cardinality constraint, but it is also declared as 'owl:TransitiveProperty'. This is not allowed in OWL-DL.", prop),
                                 String.Format("Remove the 'owl:FunctionalProperty' global cardinality constraint from the ontology property '{0}', or unset this property as 'owl:TransitiveProperty'.", prop)
                             ));
                         }

                    }
                    #endregion

                    #region InverseFunctional
                    if  (prop.IsInverseFunctionalProperty()) {
                         if (!objCache.ContainsKey(asn.TaxonomyObject.PatternMemberID)) {
                              objCache.Add(asn.TaxonomyObject.PatternMemberID, asn.TaxonomyObject);
                         }
                         else {

                              //InverseFunctionalProperty can only occur once per object fact within assertions
                              report.AddEvidence(new RDFOntologyValidationEvidence(
                                  RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                  "GlobalCardinalityConstraint",
                                  String.Format("Ontology property '{0}' has an 'owl:InverseFunctionalProperty' global cardinality constraint, which is violated by object ontology fact '{1}'.", asn.TaxonomyPredicate, asn.TaxonomyObject),
                                  String.Format("Remove the '{0} {1} {2}' assertion from the data.", asn.TaxonomySubject, asn.TaxonomyPredicate, asn.TaxonomyObject)
                              ));

                         }

                         //InverseFunctionalProperty cannot be TransitiveProperty (even indirectly)
                         if (prop.IsTransitiveProperty() || RDFOntologyReasoningHelper.EnlistSuperPropertiesOf(prop, ontology.Model.PropertyModel).Any(p => p.IsTransitiveProperty())) {
                               report.AddEvidence(new RDFOntologyValidationEvidence(
                                   RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                   "GlobalCardinalityConstraint",
                                   String.Format("Ontology property '{0}' has an 'owl:InverseFunctionalProperty' global cardinality constraint, but it is also declared as 'owl:TransitiveProperty'. This is not allowed in OWL-DL.", prop),
                                   String.Format("Remove the 'owl:InverseFunctionalProperty' global cardinality constraint from the ontology property '{0}', or unset this property as 'owl:TransitiveProperty'.", prop)
                               ));
                         }

                    }
                    #endregion

                }
            }
            #endregion

            RDFSemanticsEvents.RaiseSemanticsInfo("Completed execution of validation rule 'GlobalCardinalityConstraint'");
        }
        /// <summary>
        /// Gets an ontology data containing the facts which are members of this restriction
        /// </summary>
        public override RDFOntologyData EnlistMembers(RDFOntology ontology) {
            var resultFacts       = new RDFOntologyData();
            if (ontology         != null) {

                //Retrieve ontology data facts having the restricted property in their attributes
                var facts         = base.EnlistMembers(ontology);

                //Item2 is a counter for occurrences of the restricted property with a range fact of the restricted "FromClass"
                //Item3 is a counter for occurrences of the restricted property with a range fact not of the restricted "FromClass"
                var factsRegister = new Dictionary<Int64, Tuple<RDFOntologyFact, Int64, Int64>>();

                //Iterate the ontology data facts
                foreach(var f in facts) {

                    //Iterate the ontology attributes of the current ontology fact
                    var factOntAttributesEnum       = f.OntologyAttributesEnumerator();
                    while (factOntAttributesEnum.MoveNext()) {
                        if (factOntAttributesEnum.Current.AttributeProperty.Equals(this.OnProperty)) {
                            if (!factsRegister.ContainsKey(f.PatternMemberID)) {
                                factsRegister.Add(f.PatternMemberID, new Tuple<RDFOntologyFact, Int64, Int64>(f, 0, 0));
                            }

                            //Iterate the class types of the candidate ontology fact and check presence of the restriction "FromClass"
                            Boolean fromClassFound  = false;
                            var factClassTypesEnum  = factOntAttributesEnum.Current.AttributeValue.ClassTypesEnumerator();
                            while (!fromClassFound && factClassTypesEnum.MoveNext()) {
                                if (factClassTypesEnum.Current.Equals(this.FromClass)) {
                                    fromClassFound  = true;
                                }
                            }

                            //Update the occurrence counters of the candidate fact
                            Int64 actualEqCounter   = factsRegister[f.PatternMemberID].Item2;
                            Int64 actualDiffCounter = factsRegister[f.PatternMemberID].Item3;
                            if (fromClassFound) {
                                factsRegister[f.PatternMemberID] = new Tuple<RDFOntologyFact, Int64, Int64>(f, actualEqCounter + 1, actualDiffCounter);
                            }
                            else {
                                factsRegister[f.PatternMemberID] = new Tuple<RDFOntologyFact, Int64, Int64>(f, actualEqCounter, actualDiffCounter + 1);
                            }

                        }
                    }

                }

                //Apply the value restrictions on the candidate ontology facts
                var factsRegEnum = factsRegister.Values.GetEnumerator();
                while (factsRegEnum.MoveNext()) {
                    switch (this.Category) {
                        case RDFSemanticsEnums.RDFOntologyValuesFromRestrictionCategory.AllValuesFrom:
                            if (factsRegEnum.Current.Item2 >= 1 && factsRegEnum.Current.Item3 == 0) {
                                resultFacts.AddFact(factsRegEnum.Current.Item1);
                            }
                            break;
                        case RDFSemanticsEnums.RDFOntologyValuesFromRestrictionCategory.SomeValuesFrom:
                            if (factsRegEnum.Current.Item2 >= 1) {
                                resultFacts.AddFact(factsRegEnum.Current.Item1);
                            }
                            break;
                    }
                }

            }
            return resultFacts;
        }
        /// <summary>
        /// Validation rule checking for disjointness of vocabulary of classes, properties and facts
        /// </summary>
        internal static void Vocabulary_Disjointness(RDFOntology ontology, RDFOntologyValidationReport report) {
            RDFSemanticsEvents.RaiseSemanticsInfo("Launched execution of validation rule 'Vocabulary_Disjointness'");

            #region ClassModel
            foreach (var c in ontology.Model.ClassModel) {
                if (ontology.Model.PropertyModel.Properties.ContainsKey(c.PatternMemberID)) {
                    report.AddEvidence(new RDFOntologyValidationEvidence(
                        RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                        "Vocabulary_Disjointness",
                        String.Format("Disjointess of class model and property model is violated because the name '{0}' refers both to a class and a property.", c),
                        String.Format("Remove, or rename, one of the two entities.")
                    ));
                }
                if (ontology.Data.Facts.ContainsKey(c.PatternMemberID)) {
                    report.AddEvidence(new RDFOntologyValidationEvidence(
                        RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                        "Vocabulary_Disjointness",
                        String.Format("Disjointess of class model and data is violated because the name '{0}' refers both to a class and a fact.", c),
                        String.Format("Remove, or rename, one of the two entities.")
                    ));
                }
            }
            #endregion

            #region PropertyModel
            foreach (var p in ontology.Model.PropertyModel) {
                if (ontology.Data.Facts.ContainsKey(p.PatternMemberID)) {
                    report.AddEvidence(new RDFOntologyValidationEvidence(
                        RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                        "Vocabulary_Disjointness",
                        String.Format("Disjointess of property model and data is violated because the name '{0}' refers both to a property and a fact.", p),
                        String.Format("Remove, or rename, one of the two entities.")
                    ));
                }
            }
            #endregion

            RDFSemanticsEvents.RaiseSemanticsInfo("Completed execution of validation rule 'Vocabulary_Disjointness'");
        }
 /// <summary>
 /// Loads the classes from the given graph into the given ontology
 /// </summary>
 internal static void LoadClasses(RDFGraph ontGraph, RDFOntology ontology, RDFGraph rdfType) {
     foreach (var t in rdfType.SelectTriplesByObject(RDFVocabulary.OWL.CLASS)
                              .UnionWith(rdfType.SelectTriplesByObject(RDFVocabulary.RDFS.CLASS))) {
         ontology.Model.ClassModel.AddClass(new RDFOntologyClass((RDFResource)t.Subject));
     }
 }
        /// <summary>
        /// Loads the composite classes from the given graph into the given ontology
        /// </summary>
        internal static void LoadComposites(RDFGraph ontGraph, RDFOntology ontology) {
            var changeLog = new Dictionary<Int64, RDFOntologyClass>();
            foreach (var c in ontology.Model.ClassModel) {

                #region Union
                var unOf  = ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                    .SelectTriplesByPredicate(RDFVocabulary.OWL.UNION_OF)
                                    .FirstOrDefault();
                if(unOf  != null) {
                    if (unOf.TripleFlavor == RDFModelEnums.RDFTripleFlavors.SPO) {
                        var nilFound       = false;
                        var itemRest       = (RDFResource)unOf.Object;
                        while (!nilFound)  {

                            #region rdf:first
                            var first      = ontGraph.SelectTriplesBySubject(itemRest)
                                                     .SelectTriplesByPredicate(RDFVocabulary.RDF.FIRST)
                                                     .FirstOrDefault();
                            if( first     != null) {
                                var compClass  = ontology.Model.ClassModel.SelectClass(first.Object.ToString());
                                if (compClass != null) {
                                    if (!changeLog.ContainsKey(c.PatternMemberID)) {
                                        var ontUClass             = new RDFOntologyUnionClass();
                                        ontUClass.Value           = c.Value;
                                        ontUClass.PatternMemberID = c.PatternMemberID;
                                        ontUClass.AddCompositingClass(compClass);
                                        changeLog.Add(c.PatternMemberID, ontUClass);
                                    }
                                    else {
                                        ((RDFOntologyUnionClass)changeLog[c.PatternMemberID]).AddCompositingClass(compClass);
                                    }
                                }
                                else {
                                    throw new RDFSemanticsException("Cannot load union class from graph, because its compositing class '" + first.Object +"' has not been found in the ontology model.");
                                }

                                #region rdf:rest
                                var rest   = ontGraph.SelectTriplesBySubject(itemRest)
                                                     .SelectTriplesByPredicate(RDFVocabulary.RDF.REST)
                                                     .FirstOrDefault();
                                if(rest   != null) {
                                    if (rest.Object.Equals(RDFVocabulary.RDF.NIL)) {
                                        nilFound = true;
                                    }
                                    else {
                                        itemRest = (RDFResource)rest.Object;
                                    }
                                }
                                #endregion

                            }
                            #endregion

                        }
                    }
                }
                #endregion

                #region Intersection
                var inOf  = ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                    .SelectTriplesByPredicate(RDFVocabulary.OWL.INTERSECTION_OF)
                                    .FirstOrDefault();
                if (inOf != null) {
                    if (inOf.TripleFlavor == RDFModelEnums.RDFTripleFlavors.SPO) {
                        var nilFound       = false;
                        var itemRest       = (RDFResource)inOf.Object;
                        while (!nilFound) {

                            #region rdf:first
                            var first      = ontGraph.SelectTriplesBySubject(itemRest)
                                                     .SelectTriplesByPredicate(RDFVocabulary.RDF.FIRST)
                                                     .FirstOrDefault();
                            if (first     != null) {
                                var compClass  = ontology.Model.ClassModel.SelectClass(first.Object.ToString());
                                if (compClass != null) {
                                    if (!changeLog.ContainsKey(c.PatternMemberID)) {
                                        var ontIClass             = new RDFOntologyIntersectionClass();
                                        ontIClass.Value           = c.Value;
                                        ontIClass.PatternMemberID = c.PatternMemberID;
                                        ontIClass.AddCompositingClass(compClass);
                                        changeLog.Add(c.PatternMemberID, ontIClass);
                                    }
                                    else {
                                        ((RDFOntologyIntersectionClass)changeLog[c.PatternMemberID]).AddCompositingClass(compClass);
                                    }
                                }
                                else {
                                    throw new RDFSemanticsException("Cannot load intersection class from graph, because its compositing class '" + first.Object + "' has not been found in the ontology model.");
                                }

                                #region rdf:rest
                                var rest   = ontGraph.SelectTriplesBySubject(itemRest)
                                                     .SelectTriplesByPredicate(RDFVocabulary.RDF.REST)
                                                     .FirstOrDefault();
                                if (rest  != null) {
                                    if (rest.Object.Equals(RDFVocabulary.RDF.NIL)) {
                                        nilFound = true;
                                    }
                                    else {
                                        itemRest = (RDFResource)rest.Object;
                                    }
                                }
                                #endregion

                            }
                            #endregion

                        }
                    }
                }
                #endregion

                #region Complement
                var cmOf  = ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                    .SelectTriplesByPredicate(RDFVocabulary.OWL.COMPLEMENT_OF)
                                    .FirstOrDefault();
                if (cmOf != null) {
                    if (cmOf.TripleFlavor == RDFModelEnums.RDFTripleFlavors.SPO) {
                        var compClass      = ontology.Model.ClassModel.SelectClass(cmOf.Object.ToString());
                        if (compClass     != null) {
                            if (!changeLog.ContainsKey(c.PatternMemberID)) {
                                var ontCClass             = new RDFOntologyComplementClass(compClass);
                                ontCClass.Value           = c.Value;
                                ontCClass.PatternMemberID = c.PatternMemberID;
                                changeLog.Add(c.PatternMemberID, ontCClass);
                            }
                        }
                        else {
                            throw new RDFSemanticsException("Cannot load complement class from graph, because its complemented class '" + cmOf.Object + "' has not been found in the ontology model.");
                        }
                    }
                }
                #endregion

            }
            foreach (var cl in changeLog) {
                ontology.Model.ClassModel.Classes[cl.Key] = cl.Value;
            }
        }
        /// <summary>
        /// Loads the class taxonomies from the given graph into the given ontology
        /// </summary>
        internal static void LoadClassTaxonomies(RDFGraph ontGraph, RDFOntology ontology) {
            foreach (var c in ontology.Model.ClassModel) {

                #region Hierarchy
                foreach (var t in ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                          .SelectTriplesByPredicate(RDFVocabulary.RDFS.SUB_CLASS_OF)) {

                    //Check conditions to accept the class
                    var superClass  = ontology.Model.ClassModel.SelectClass(t.Object.ToString());
                    if (superClass != null) {
                        c.AddSuperClass(superClass);
                    }
                    else {
                        throw new RDFSemanticsException("Cannot load taxonomy of class '" + c.Value + "', because its superclass '" + t.Object + "' has not been found in the ontology model.");
                    }

                }
                #endregion

                #region Equivalence
                foreach (var t in ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                          .SelectTriplesByPredicate(RDFVocabulary.OWL.EQUIVALENT_CLASS)) {

                    //Check conditions to accept the class
                    var equivClass  = ontology.Model.ClassModel.SelectClass(t.Object.ToString());
                    if (equivClass != null) {
                        c.AddEquivalentClass(equivClass);
                    }
                    else {
                        throw new RDFSemanticsException("Cannot load taxonomy of class '" + c.Value + "', because its equivalent class '" + t.Object + "' has not been found in the ontology model.");
                    }

                }
                #endregion

                #region Disjointness
                foreach (var t in ontGraph.SelectTriplesBySubject((RDFResource)c.Value)
                                          .SelectTriplesByPredicate(RDFVocabulary.OWL.DISJOINT_WITH)) {

                    //Check conditions to accept the class
                    var disjClass  = ontology.Model.ClassModel.SelectClass(t.Object.ToString());
                    if (disjClass != null) {
                        c.AddDisjointClass(disjClass);
                    }
                    else {
                        throw new RDFSemanticsException("Cannot load taxonomy of class '" + c.Value + "', because its disjoint class '" + t.Object + "' has not been found in the ontology model.");
                    }

                }
                #endregion

            }
        }
        /// <summary>
        /// Gets an ontology data containing the facts which are members of this restriction
        /// </summary>
        public override RDFOntologyData EnlistMembers(RDFOntology ontology)  {
            var resultFacts       = new RDFOntologyData();
            if (ontology         != null) {

                //Retrieve ontology data facts having the restricted property in their attributes
                var facts         = base.EnlistMembers(ontology);

                //Item2 is a counter for occurrences of the restricted property within the key fact
                var factsRegister = new Dictionary<Int64, Tuple<RDFOntologyFact, Int64>>();

                //Iterate the retrieved ontology data facts
                foreach(var f in facts) {

                    //Iterate the ontology attributes of the current ontology fact
                    var factOntAttributesEnum = f.OntologyAttributesEnumerator();
                    while (factOntAttributesEnum.MoveNext()) {
                        if (factOntAttributesEnum.Current.AttributeProperty.Equals(this.OnProperty)) {
                                //Register the ontology data fact or update its property occurrence counter
                                if (!factsRegister.ContainsKey(f.PatternMemberID)) {
                                    factsRegister.Add(f.PatternMemberID, new Tuple<RDFOntologyFact, Int64>(f, 1));
                                }
                                else {
                                    Int64 actualCounter = factsRegister[f.PatternMemberID].Item2;
                                    factsRegister[f.PatternMemberID] = new Tuple<RDFOntologyFact, Int64>(f, actualCounter + 1);
                                }
                        }
                    }

                }

                //Apply the cardinality restrictions on the candidate ontology facts
                var factsRegEnum  = factsRegister.Values.GetEnumerator();
                while (factsRegEnum.MoveNext()) {
                    Boolean passesMinCardinality = true;
                    Boolean passesMaxCardinality = true;

                    //MinCardinality: signal candidate facts having "#occurrences < MinCardinality"
                    if (this.MinCardinality > 0) {
                        if (factsRegEnum.Current.Item2 < this.MinCardinality) {
                            passesMinCardinality = false;                            
                        }
                    }

                    //MaxCardinality: signal candidate facts having "#occurrences > MaxCardinality"
                    if (this.MaxCardinality > 0) {
                        if (factsRegEnum.Current.Item2 > this.MaxCardinality) {
                            passesMaxCardinality = false;
                        }
                    }

                    //Save the candidate fact if it passes cardinality restrictions
                    if (passesMinCardinality && passesMaxCardinality) {
                        resultFacts.AddFact(factsRegEnum.Current.Item1);
                    }
                }

            }
            return resultFacts;
        }
        /// <summary>
        /// Validation rule checking for consistency of rdfs:domain and rdfs:range axioms
        /// </summary>
        internal static void Domain_Range(RDFOntology ontology, RDFOntologyValidationReport report) {
            RDFSemanticsEvents.RaiseSemanticsInfo("Launched execution of validation rule 'Domain_Range'");

            #region Domain_Range
            var classCache    = new Dictionary<Int64, RDFOntologyData>();
            var litCheckCache = new Dictionary<Int64, Boolean>();
            foreach (var assertion  in ontology.Data.Relations.Assertions.Where(asn =>
                                                        ((RDFOntologyProperty)asn.TaxonomyPredicate).Domain != null  ||
                                                        ((RDFOntologyProperty)asn.TaxonomyPredicate).Range  != null)) {

                #region Domain
                var domain    = ((RDFOntologyProperty)assertion.TaxonomyPredicate).Domain;
                if (domain   != null) {

                    //Domain class cannot be a datarange or compatible with rdfs:Literal
                    if (!litCheckCache.ContainsKey(domain.PatternMemberID)) {
                         litCheckCache.Add(domain.PatternMemberID, RDFOntologyReasoningHelper.IsLiteralCompatibleClass(domain, ontology.Model.ClassModel));
                    }
                    if (litCheckCache[domain.PatternMemberID]) {
                        report.AddEvidence(new RDFOntologyValidationEvidence(
                            RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                            "Domain_Range",
                            String.Format("Violation of 'rdfs:domain' constraint on property '{0}': ontology class '{1}' cannot be compatible with 'rdfs:Literal'.", assertion.TaxonomyPredicate, domain),
                            String.Format("Review relations of ontology class '{0}'.", domain)
                        ));
                    }
                    else {

                        //Cache-Miss
                        if (!classCache.ContainsKey(domain.PatternMemberID)) {
                             classCache.Add(domain.PatternMemberID, RDFOntologyReasoningHelper.EnlistMembersOf(domain, ontology));
                        }

                        //Cache-Check
                        if (classCache[domain.PatternMemberID].SelectFact(assertion.TaxonomySubject.ToString()) == null) {
                            report.AddEvidence(new RDFOntologyValidationEvidence(
                                RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                "Domain_Range",
                                String.Format("Violation of 'rdfs:domain' constraint on property '{0}': ontology fact '{1}' is incompatible with domain class '{2}'.", assertion.TaxonomyPredicate, assertion.TaxonomySubject, domain),
                                String.Format("Review classtypes of ontology fact '{0}'.", assertion.TaxonomySubject)
                            ));
                        }

                    }

                }
                #endregion

                #region Range
                var range     = ((RDFOntologyProperty)assertion.TaxonomyPredicate).Range;
                if (range    != null) {
                    if (((RDFOntologyProperty)assertion.TaxonomyPredicate).IsObjectProperty()) {

                        //Cache-Miss
                        if (!classCache.ContainsKey(range.PatternMemberID)) {
                             classCache.Add(range.PatternMemberID, RDFOntologyReasoningHelper.EnlistMembersOf(range, ontology));
                        }

                        //Cache-Check
                        if (classCache[range.PatternMemberID].SelectFact(assertion.TaxonomyObject.ToString()) == null) {
                            report.AddEvidence(new RDFOntologyValidationEvidence(
                                RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                "Domain_Range",
                                String.Format("Violation of 'rdfs:range' constraint on property '{0}': ontology fact '{1}' is incompatible with range class '{2}'.", assertion.TaxonomyPredicate, assertion.TaxonomyObject, range),
                                String.Format("Review classtypes of ontology fact '{0}'.", assertion.TaxonomyObject)
                            ));
                        }

                    }
                    else {

                        //Cache-Miss
                        if (!classCache.ContainsKey(range.PatternMemberID)) {
                             classCache.Add(range.PatternMemberID, RDFOntologyReasoningHelper.EnlistMembersOf(range, ontology));
                        }

                        //Cache-Check
                        if (classCache[range.PatternMemberID].SelectLiteral(assertion.TaxonomyObject.ToString()) == null) {
                            report.AddEvidence(new RDFOntologyValidationEvidence(
                                RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                                "Domain_Range",
                                String.Format("Violation of 'rdfs:range' constraint on property '{0}': ontology literal '{1}' is incompatible with range class '{2}'.", assertion.TaxonomyPredicate, assertion.TaxonomyObject, range),
                                String.Format("Review datatype of ontology literal '{0}'.", assertion.TaxonomyObject)
                            ));
                        }

                    }
                }
                #endregion

            }
            #endregion

            RDFSemanticsEvents.RaiseSemanticsInfo("Completed execution of validation rule 'Domain_Range'");
        }
 /// <summary>
 /// Checks if the given fact is member of the given class within the given ontology
 /// </summary>
 public static Boolean IsMemberOf(RDFOntologyFact ontFact,
                                  RDFOntologyClass ontClass,
                                  RDFOntology ontology)
 {
     return(ontFact != null && ontClass != null && ontology != null ? EnlistMembersOf(ontClass, ontology).Facts.ContainsKey(ontFact.PatternMemberID) : false);
 }
        /// <summary>
        /// Loads the fact instances from the given graph into the given ontology
        /// </summary>
        internal static void LoadFacts(RDFGraph ontGraph, RDFOntology ontology, RDFGraph rdfType) {

            #region Facts
            foreach (var c in ontology.Model.ClassModel) {
                foreach (var t in rdfType.SelectTriplesByObject((RDFResource)c.Value)) {                    
                    var fct  = ontology.Data.SelectFact(t.Subject.ToString());
                    if (fct == null) {
                        fct  = new RDFOntologyFact((RDFResource)t.Subject);                        
                        ontology.Data.AddFact(fct); 
                    }
                    fct.AddClassType(c);
                }
            }
            #endregion

            #region Attributes
            foreach (var attrProp  in ontology.Model.PropertyModel) {
                if (!attrProp.IsAnnotationProperty()) {
                    foreach (var t in ontGraph.SelectTriplesByPredicate((RDFResource)attrProp.Value)) {

                        //Do not parse attributes of the ontology
                        if (!t.Subject.Equals(ontology.Value)) {

                            var subjFct        = ontology.Data.SelectFact(t.Subject.ToString());
                            if (subjFct       != null) {
                                var objFct     = ontology.Data.SelectFact(t.Object.ToString());
                                if (objFct    != null) {
                                    subjFct.AddOntologyAttribute(attrProp, objFct);
                                }
                                else {
                                    if (t.TripleFlavor == RDFModelEnums.RDFTripleFlavors.SPO) {
                                        throw new RDFSemanticsException("Cannot load attributes of fact '" + t.Subject + "' from graph, because it has a range object fact '" + t.Object + "' which has not been found in the ontology data.");
                                    }
                                    else {
                                        //Literal fact must be created on the fly, since they do not exist in ontology data
                                        objFct = new RDFOntologyFact((RDFLiteral)t.Object);
                                        ontology.Data.AddFact(objFct);
                                        subjFct.AddOntologyAttribute(attrProp, objFct);
                                    }
                                }
                            }
                            else {
                                throw new RDFSemanticsException("Cannot load attributes of fact '" + t.Subject + "' from graph, because it has not been found in the ontology data.");
                            }

                        }

                    }
                }
            }
            #endregion

            #region SameAs
            foreach (var t     in ontGraph.SelectTriplesByPredicate(RDFVocabulary.OWL.SAME_AS)) {
                var subjFct     = ontology.Data.SelectFact(t.Subject.ToString());
                if (subjFct    != null) {
                    var objFct  = ontology.Data.SelectFact(t.Object.ToString());
                    if (objFct != null) {
                        subjFct.AddSameAs(objFct);
                    }
                    else {
                        throw new RDFSemanticsException("Cannot load taxonomy of fact '" + t.Subject + "' from graph, because its equivalent fact '" + t.Object + "' has not been found in the ontology data.");
                    }
                }
                else {
                    throw new RDFSemanticsException("Cannot load taxonomy of fact '" + t.Subject + "' from graph, because it has not been found in the ontology data.");
                }
            }
            #endregion

            #region DifferentFrom
            foreach (var t in ontGraph.SelectTriplesByPredicate(RDFVocabulary.OWL.DIFFERENT_FROM)) {
                var subjFct     = ontology.Data.SelectFact(t.Subject.ToString());
                if (subjFct    != null) {
                    var objFct  = ontology.Data.SelectFact(t.Object.ToString());
                    if (objFct != null) {
                        subjFct.AddDifferentFrom(objFct);
                    }
                    else {
                        throw new RDFSemanticsException("Cannot load taxonomy of fact '" + t.Subject + "' from graph, because its different fact '" + t.Object + "' has not been found in the ontology data.");
                    }
                }
                else {
                    throw new RDFSemanticsException("Cannot load taxonomy of fact '" + t.Subject + "' from graph, because it has not been found in the ontology data.");
                }
            }
            #endregion

        }
        /// <summary>
        /// Gets an ontology data containing the facts which are members of this class
        /// </summary>
        public override RDFOntologyData EnlistMembers(RDFOntology ontology) {
            var facts             = new RDFOntologyData();
            if (ontology         != null) {

                //Iterate the classes belonging to the union class
                var compClassEnum = this.CompositingClassesEnumerator();
                while (compClassEnum.MoveNext()) {

                    //Compose them with a union logic
                    facts         = facts.UnionWith(compClassEnum.Current.EnlistMembers(ontology));

                }

            }
            return facts;
        }
        /// <summary>
        /// Validation rule checking for declaration of classes, properties and facts
        /// </summary>
        internal static void Vocabulary_Declaration(RDFOntology ontology, RDFOntologyValidationReport report) {
            RDFSemanticsEvents.RaiseSemanticsInfo("Launched execution of validation rule 'Vocabulary_Declaration'");

            #region Classes

            //SubClassOf
            foreach (var   c in ontology.Model.ClassModel.Relations.SubClassOf) {
                if  (!ontology.Model.ClassModel.Classes.ContainsKey(c.TaxonomySubject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by a 'rdfs:subclassOf' relation.", c),
                          String.Format("Add declaration of ontology class '{0}' to the class model.", c.TaxonomySubject)
                      ));
                }
                if (!ontology.Model.ClassModel.Classes.ContainsKey(c.TaxonomyObject.PatternMemberID)) {
                     report.AddEvidence(new RDFOntologyValidationEvidence(
                         RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                         "Vocabulary_Declaration",
                         String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by a 'rdfs:subclassOf' relation.", c),
                         String.Format("Add declaration of ontology class '{0}' to the class model.", c.TaxonomyObject)
                     ));
                }
            }

            //EquivalentClass
            foreach (var   c in ontology.Model.ClassModel.Relations.EquivalentClass) {
                if  (!ontology.Model.ClassModel.Classes.ContainsKey(c.TaxonomySubject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by an 'owl:EquivalentClass' relation.", c),
                          String.Format("Add declaration of ontology class '{0}' to the class model.", c.TaxonomySubject)
                      ));
                }
                if (!ontology.Model.ClassModel.Classes.ContainsKey(c.TaxonomyObject.PatternMemberID)) {
                     report.AddEvidence(new RDFOntologyValidationEvidence(
                         RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                         "Vocabulary_Declaration",
                         String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by an 'owl:EquivalentClass' relation.", c),
                         String.Format("Add declaration of ontology class '{0}' to the class model.", c.TaxonomyObject)
                     ));
                }
            }

            //DisjointWith
            foreach (var   c in ontology.Model.ClassModel.Relations.DisjointWith) {
                if  (!ontology.Model.ClassModel.Classes.ContainsKey(c.TaxonomySubject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by an 'owl:DisjointWith' relation.", c),
                          String.Format("Add declaration of ontology class '{0}' to the class model.", c.TaxonomySubject)
                     ));
                }
                if (!ontology.Model.ClassModel.Classes.ContainsKey(c.TaxonomyObject.PatternMemberID)) {
                     report.AddEvidence(new RDFOntologyValidationEvidence(
                         RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                         "Vocabulary_Declaration",
                         String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by an 'owl:DisjointWith' relation.", c),
                         String.Format("Add declaration of ontology class '{0}' to the class model.", c.TaxonomyObject)
                     ));
                }
            }

            //OneOf
            foreach (var   c in ontology.Model.ClassModel.Relations.OneOf) {
                if  (!ontology.Model.ClassModel.Classes.ContainsKey(c.TaxonomySubject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by an 'owl:oneOf' relation.", c),
                          String.Format("Add declaration of ontology class '{0}' to the class model.", c.TaxonomySubject)
                     ));
                }
            }

            //IntersectionOf
            foreach (var   c in ontology.Model.ClassModel.Relations.IntersectionOf) {
                if  (!ontology.Model.ClassModel.Classes.ContainsKey(c.TaxonomySubject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by an 'owl:intersectionOf' relation.", c),
                          String.Format("Add declaration of ontology class '{0}' to the class model.", c.TaxonomySubject)
                     ));
                }
                if (!ontology.Model.ClassModel.Classes.ContainsKey(c.TaxonomyObject.PatternMemberID)) {
                     report.AddEvidence(new RDFOntologyValidationEvidence(
                         RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                         "Vocabulary_Declaration",
                         String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by an 'owl:intersectionOf' relation.", c),
                         String.Format("Add declaration of ontology class '{0}' to the class model.", c.TaxonomyObject)
                     ));
                }
            }

            //UnionOf
            foreach (var   c in ontology.Model.ClassModel.Relations.UnionOf) {
                if  (!ontology.Model.ClassModel.Classes.ContainsKey(c.TaxonomySubject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by an 'owl:unionOf' relation.", c),
                          String.Format("Add declaration of ontology class '{0}' to the class model.", c.TaxonomySubject)
                     ));
                }
                if (!ontology.Model.ClassModel.Classes.ContainsKey(c.TaxonomyObject.PatternMemberID)) {
                     report.AddEvidence(new RDFOntologyValidationEvidence(
                         RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                         "Vocabulary_Declaration",
                         String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by an 'owl:unionOf' relation.", c),
                         String.Format("Add declaration of ontology class '{0}' to the class model.", c.TaxonomyObject)
                     ));
                }
            }

            //ComplementOf
            foreach (var complCls  in ontology.Model.ClassModel.Where(c => c is RDFOntologyComplementClass).OfType<RDFOntologyComplementClass>()) {
                if  (!ontology.Model.ClassModel.Classes.ContainsKey(complCls.ComplementOf.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology class '{0}' is not found in the class model: complement class '{1}' requires it.", complCls.ComplementOf, complCls),
                          String.Format("Add declaration of ontology class '{0}' to the class model.", complCls.ComplementOf)
                      ));
                }
            }

            //Domain / Range
            foreach (var p in ontology.Model.PropertyModel.Where(prop => prop.Domain != null || prop.Range != null)) {
                if  (p.Domain != null) {
                     if (!ontology.Model.ClassModel.Classes.ContainsKey(p.Domain.PatternMemberID)) {
                          report.AddEvidence(new RDFOntologyValidationEvidence(
                              RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                              "Vocabulary_Declaration",
                              String.Format("Declaration of ontology class '{0}' is not found in the class model: ontology property '{1}' requires it as 'rdfs:domain'.", p.Domain, p),
                              String.Format("Add declaration of ontology class '{0}' to the class model.", p.Domain)
                          ));
                     }
                }
                if  (p.Range != null) {
                     if (!ontology.Model.ClassModel.Classes.ContainsKey(p.Range.PatternMemberID)) {
                          report.AddEvidence(new RDFOntologyValidationEvidence(
                              RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                              "Vocabulary_Declaration",
                              String.Format("Declaration of ontology class '{0}' is not found in the class model: ontology property '{1}' requires it as 'rdfs:range'.", p.Range, p),
                              String.Format("Add declaration of ontology class '{0}' to the class model.", p.Range)
                          ));
                     }
                }
            }

            #endregion

            #region Restrictions

            var restrEnum  = ontology.Model.ClassModel.RestrictionsEnumerator;
            while(restrEnum.MoveNext()) {

                //OnProperty
                var onProp = restrEnum.Current.OnProperty;
                if (!ontology.Model.PropertyModel.Properties.ContainsKey(onProp.Value.PatternMemberID)) {
                     report.AddEvidence(new RDFOntologyValidationEvidence(
                         RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                         "Vocabulary_Declaration",
                         String.Format("Declaration of ontology property '{0}' is not found in the property model: restriction class '{1}' requires it as 'owl:OnProperty'.", onProp, restrEnum.Current),
                         String.Format("Add declaration of ontology property '{0}' to the property model.", onProp)
                     ));
                }

                // AllValuesFrom
                if (restrEnum.Current is RDFOntologyAllValuesFromRestriction) {
                    var fromClass = ((RDFOntologyAllValuesFromRestriction)restrEnum.Current).FromClass;
                    if (!ontology.Model.ClassModel.Classes.ContainsKey(fromClass.Value.PatternMemberID)) {
                         report.AddEvidence(new RDFOntologyValidationEvidence(
                             RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                             "Vocabulary_Declaration",
                             String.Format("Declaration of ontology class '{0}' is not found in the class model: restriction class '{1}' requires it as 'owl:FromClass'.", fromClass, restrEnum.Current),
                             String.Format("Add declaration of ontology class '{0}' to the class model.", fromClass)
                         ));
                    }
                }

                // SomeValuesFrom
                else if (restrEnum.Current is RDFOntologySomeValuesFromRestriction) {
                    var fromClass = ((RDFOntologySomeValuesFromRestriction)restrEnum.Current).FromClass;
                    if (!ontology.Model.ClassModel.Classes.ContainsKey(fromClass.Value.PatternMemberID)) {
                         report.AddEvidence(new RDFOntologyValidationEvidence(
                             RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                             "Vocabulary_Declaration",
                             String.Format("Declaration of ontology class '{0}' is not found in the class model: restriction class '{1}' requires it as 'owl:FromClass'.", fromClass, restrEnum.Current),
                             String.Format("Add declaration of ontology class '{0}' to the class model.", fromClass)
                         ));
                    }
                }

                // HasValue
                else if (restrEnum.Current is RDFOntologyHasValueRestriction) {
                    var  requiredValue =    ((RDFOntologyHasValueRestriction)restrEnum.Current).RequiredValue;
                    if  (requiredValue.IsFact() && !ontology.Data.Facts.ContainsKey(requiredValue.Value.PatternMemberID)) {
                         report.AddEvidence(new RDFOntologyValidationEvidence(
                             RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                             "Vocabulary_Declaration",
                             String.Format("Declaration of ontology fact '{0}' is not found in the data: restriction class '{1}' requires it as 'owl:RequiredValue'.", requiredValue, restrEnum.Current),
                             String.Format("Add declaration of ontology fact '{0}' to the data.", requiredValue)
                         ));
                    }
                }

            }

            #endregion

            #region Properties

            //SubPropertyOf
            foreach (var   p in ontology.Model.PropertyModel.Relations.SubPropertyOf) {
                if  (!ontology.Model.PropertyModel.Properties.ContainsKey(p.TaxonomySubject.Value.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology property '{0}' is not found in the property model: it is required by a 'rdfs:subpropertyOf' relation.", p),
                          String.Format("Add declaration of ontology property '{0}' to the property model.", p.TaxonomySubject)
                     ));
                }
                if (!ontology.Model.PropertyModel.Properties.ContainsKey(p.TaxonomyObject.Value.PatternMemberID)) {
                     report.AddEvidence(new RDFOntologyValidationEvidence(
                         RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                         "Vocabulary_Declaration",
                         String.Format("Declaration of ontology property '{0}' is not found in the property model: it is required by a 'rdfs:subpropertyOf' relation.", p),
                         String.Format("Add declaration of ontology property '{0}' to the property model.", p.TaxonomyObject)
                     ));
                }
            }

            //EquivalentProperty
            foreach (var   p in ontology.Model.PropertyModel.Relations.EquivalentProperty) {
                if  (!ontology.Model.PropertyModel.Properties.ContainsKey(p.TaxonomySubject.Value.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology property '{0}' is not found in the property model: it is required by an 'owl:EquivalentProperty' relation.", p),
                          String.Format("Add declaration of ontology property '{0}' to the property model.", p.TaxonomySubject)
                     ));
                }
                if (!ontology.Model.PropertyModel.Properties.ContainsKey(p.TaxonomyObject.Value.PatternMemberID)) {
                     report.AddEvidence(new RDFOntologyValidationEvidence(
                         RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                         "Vocabulary_Declaration",
                         String.Format("Declaration of ontology property '{0}' is not found in the property model: it is required by an 'owl:EquivalentProperty' relation.", p),
                         String.Format("Add declaration of ontology property '{0}' to the property model.", p.TaxonomyObject)
                     ));
                }
            }

            //InverseOf
            foreach (var   p in ontology.Model.PropertyModel.Relations.InverseOf) {
                if (!ontology.Model.PropertyModel.Properties.ContainsKey(p.TaxonomySubject.Value.PatternMemberID)) {
                     report.AddEvidence(new RDFOntologyValidationEvidence(
                         RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                         "Vocabulary_Declaration",
                         String.Format("Declaration of ontology property '{0}' is not found in the property model: it is required by an 'owl:InverseOf' relation.", p),
                         String.Format("Add declaration of ontology property '{0}' to the property model.", p.TaxonomySubject)
                     ));
                }
                if (!ontology.Model.PropertyModel.Properties.ContainsKey(p.TaxonomyObject.Value.PatternMemberID)) {
                     report.AddEvidence(new RDFOntologyValidationEvidence(
                         RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                         "Vocabulary_Declaration",
                         String.Format("Declaration of ontology property '{0}' is not found in the property model: it is required by an 'owl:InverseOf' relation.", p),
                         String.Format("Add declaration of ontology property '{0}' to the property model.", p.TaxonomyObject)
                     ));
                }
            }

            #endregion

            #region Facts

            //ClassType
            foreach (var f in ontology.Data.Relations.ClassType) {
                if  (!ontology.Data.Facts.ContainsKey(f.TaxonomySubject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology fact '{0}' is not found in the data: it is required by a 'rdf:type' relation.", f.TaxonomySubject),
                          String.Format("Add declaration of ontology fact '{0}' to the data.", f.TaxonomySubject)
                      ));
                }
                if  (!ontology.Model.ClassModel.Classes.ContainsKey(f.TaxonomyObject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology class '{0}' is not found in the class model: it is required by a 'rdf:type' relation.", f.TaxonomyObject),
                          String.Format("Add declaration of ontology class '{0}' to the class model.", f.TaxonomyObject)
                      ));
                }
            }
            foreach (var f in ontology.Data.Where(fact => ontology.Data.Relations.ClassType.SelectEntriesBySubject(fact).EntriesCount == 0)) {
                report.AddEvidence(new RDFOntologyValidationEvidence(
                    RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Error,
                    "Vocabulary_Declaration",
                    String.Format("Ontology fact '{0}' is found in the data, but it does not have classtype definitions.", f),
                    String.Format("Add at least one classtype definition for ontology fact '{0}' to the data.", f)
                ));
            }

            //SameAs
            foreach (var f in ontology.Data.Relations.SameAs) {
                if  (!ontology.Data.Facts.ContainsKey(f.TaxonomySubject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology fact '{0}' is not found in the data: it is required by a 'owl:sameAs' relation.", f.TaxonomySubject),
                          String.Format("Add declaration of ontology fact '{0}' to the data.", f.TaxonomySubject)
                      ));
                }
                if  (!ontology.Data.Facts.ContainsKey(f.TaxonomyObject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology fact '{0}' is not found in the data: it is required by a 'owl:sameAs' relation.", f.TaxonomyObject),
                          String.Format("Add declaration of ontology fact '{0}' to the data.", f.TaxonomyObject)
                      ));
                }
            }

            //DifferentFrom
            foreach (var f in ontology.Data.Relations.DifferentFrom) {
                if  (!ontology.Data.Facts.ContainsKey(f.TaxonomySubject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology fact '{0}' is not found in the data: it is required by a 'owl:differentFrom' relation.", f.TaxonomySubject),
                          String.Format("Add declaration of ontology fact '{0}' to the data.", f.TaxonomySubject)
                      ));
                }
                if  (!ontology.Data.Facts.ContainsKey(f.TaxonomyObject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology fact '{0}' is not found in the data: it is required by a 'owl:differentFrom' relation.", f.TaxonomyObject),
                          String.Format("Add declaration of ontology fact '{0}' to the data.", f.TaxonomyObject)
                      ));
                }
            }

            //Assertions
            foreach (var f in ontology.Data.Relations.Assertions) {
                if  (!ontology.Data.Facts.ContainsKey(f.TaxonomySubject.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology fact '{0}' is not found in the data: it is required by an assertion relation.", f.TaxonomySubject),
                          String.Format("Add declaration of ontology fact '{0}' to the data.", f.TaxonomySubject)
                      ));
                }
                if  (!ontology.Model.PropertyModel.Properties.ContainsKey(f.TaxonomyPredicate.PatternMemberID)) {
                      report.AddEvidence(new RDFOntologyValidationEvidence(
                          RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                          "Vocabulary_Declaration",
                          String.Format("Declaration of ontology property '{0}' is not found in the property model: it is required by an assertion relation.", f.TaxonomyPredicate),
                          String.Format("Add declaration of ontology property '{0}' to the property model.", f.TaxonomyPredicate)
                      ));
                }
                if  (f.TaxonomyPredicate.IsObjectProperty()) {
                     if (!ontology.Data.Facts.ContainsKey(f.TaxonomyObject.PatternMemberID)) {
                          report.AddEvidence(new RDFOntologyValidationEvidence(
                              RDFSemanticsEnums.RDFOntologyValidationEvidenceCategory.Warning,
                              "Vocabulary_Declaration",
                              String.Format("Declaration of ontology fact '{0}' is not found in the data: it is required by an assertion relation.", f.TaxonomyObject),
                              String.Format("Add declaration of ontology fact '{0}' to the data.", f.TaxonomyObject)
                          ));
                     }
                }
            }

            #endregion

            RDFSemanticsEvents.RaiseSemanticsInfo("Completed execution of validation rule 'Vocabulary_Declaration'");
        }