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