/// <summary> /// Adds the "aFact -> objectProperty -> bFact" relation to the data /// </summary> public RDFOntologyData AddAssertionRelation(RDFOntologyFact aFact, RDFOntologyObjectProperty objectProperty, RDFOntologyFact bFact) { if (aFact != null && objectProperty != null && bFact != null) { //Enforce preliminary check on usage of BASE properties if (!RDFOntologyChecker.CheckReservedProperty(objectProperty)) { //Enforce taxonomy checks before adding the assertion //Creation of transitive cycles is not allowed (OWL-DL) if (RDFOntologyChecker.CheckTransitiveAssertionCompatibility(this, aFact, objectProperty, bFact)) { this.Relations.Assertions.AddEntry(new RDFOntologyTaxonomyEntry(aFact, objectProperty, bFact)); } else { //Raise warning event to inform the user: Assertion relation cannot be added to the data because it violates the taxonomy transitive consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("Assertion relation between fact '{0}' and fact '{1}' with transitive property '{2}' cannot be added to the data because it would violate the taxonomy consistency (transitive cycle detected).", aFact, bFact, objectProperty)); } } else { //Raise warning event to inform the user: Assertion relation cannot be added to the data because usage of BASE reserved properties compromises the taxonomy consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("Assertion relation between fact '{0}' and fact '{1}' cannot be added to the data because usage of BASE reserved properties compromises the taxonomy consistency.", aFact, bFact)); } } return(this); }
/// <summary> /// Adds the "ontologyFact -> rdf:type -> ontologyClass" relation to the data. /// </summary> public RDFOntologyData AddClassTypeRelation(RDFOntologyFact ontologyFact, RDFOntologyClass ontologyClass) { if (ontologyFact != null && ontologyClass != null) { //Enforce preliminary check on usage of BASE classes if (!RDFOntologyChecker.CheckReservedClass(ontologyClass)) { //Enforce taxonomy checks before adding the ClassType relation if (RDFOntologyChecker.CheckClassTypeCompatibility(ontologyClass)) { this.Relations.ClassType.AddEntry(new RDFOntologyTaxonomyEntry(ontologyFact, RDFVocabulary.RDF.TYPE.ToRDFOntologyObjectProperty(), ontologyClass)); } else { //Raise warning event to inform the user: ClassType relation cannot be added to the data because only plain classes can be explicitly assigned as class types of facts RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("ClassType relation between fact '{0}' and class '{1}' cannot be added to the data because only plain classes can be explicitly assigned as class types of facts.", ontologyFact, ontologyClass)); } } else { //Raise warning event to inform the user: ClassType relation cannot be added to the data because usage of BASE reserved classes compromises the taxonomy consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("ClassType relation between fact '{0}' and class '{1}' cannot be added to the data because because usage of BASE reserved classes compromises the taxonomy consistency.", ontologyFact, ontologyClass)); } } return(this); }
/// <summary> /// Applies the given SPARQL SELECT query to the given ontology (which is converted into /// a RDF graph including semantic inferences in respect of the given export behavior) /// </summary> public static RDFSelectQueryResult ApplyToOntology(this RDFSelectQuery selectQuery, RDFOntology ontology, RDFSemanticsEnums.RDFOntologyInferenceExportBehavior ontologyInferenceExportBehavior = RDFSemanticsEnums.RDFOntologyInferenceExportBehavior.ModelAndData) { var result = new RDFSelectQueryResult(); if (selectQuery != null) { if (ontology != null) { RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Ontology '{0}' is going to be converted into a graph on which the SPARQL SELECT query will be applied. Please, remember that if the ontology validation has raised warnings or errors, you may get unexpected query results due to inconsistent semantic inferences!", ontology.Value)); var ontGraph = ontology.ToRDFGraph(ontologyInferenceExportBehavior); return(selectQuery.ApplyToGraph(ontGraph)); } } return(result); }
/// <summary> /// Analyzes the given ontology and produces a detailed report of found evidences /// </summary> internal RDFOntologyValidatorReport AnalyzeOntology(RDFOntology ontology) { var report = new RDFOntologyValidatorReport(); RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Validator is going to be applied on Ontology '{0}'", ontology.Value)); //Expand ontology ontology = ontology.UnionWith(RDFBASEOntology.Instance); //Execute rules Parallel.ForEach(this.Rules, rule => { rule.ExecuteRule(ontology, report); }); //Unexpand ontology ontology = ontology.DifferenceWith(RDFBASEOntology.Instance); RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Validator has been applied on Ontology '{0}'", ontology.Value)); return(report); }
/// <summary> /// Adds the "aFact -> owl:differentFrom -> bFact" relation to the data /// </summary> public RDFOntologyData AddDifferentFromRelation(RDFOntologyFact aFact, RDFOntologyFact bFact) { if (aFact != null && bFact != null && !aFact.Equals(bFact)) { //Enforce taxonomy checks before adding the DifferentFrom relation if (RDFOntologyChecker.CheckDifferentFromCompatibility(this, aFact, bFact)) { this.Relations.DifferentFrom.AddEntry(new RDFOntologyTaxonomyEntry(aFact, RDFVocabulary.OWL.DIFFERENT_FROM.ToRDFOntologyObjectProperty(), bFact)); this.Relations.DifferentFrom.AddEntry(new RDFOntologyTaxonomyEntry(bFact, RDFVocabulary.OWL.DIFFERENT_FROM.ToRDFOntologyObjectProperty(), aFact).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.API)); } else { //Raise warning event to inform the user: DifferentFrom relation cannot be added to the data because it violates the taxonomy consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("DifferentFrom relation between fact '{0}' and fact '{1}' cannot be added to the data because it violates the taxonomy consistency.", aFact, bFact)); } } return(this); }
/// <summary> /// Adds the "aFact -> owl:differentFrom -> bFact" relation to the data /// </summary> public RDFOntologyData AddDifferentFromRelation(RDFOntologyFact aFact, RDFOntologyFact bFact) { if (aFact != null && bFact != null && !aFact.Equals(bFact)) { //Enforce taxonomy checks before adding the differentFrom relation if (!RDFBASEOntologyReasoningHelper.IsSameFactAs(aFact, bFact, this)) { this.Relations.DifferentFrom.AddEntry(new RDFOntologyTaxonomyEntry(aFact, RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.OWL.DIFFERENT_FROM.ToString()), bFact)); this.Relations.DifferentFrom.AddEntry(new RDFOntologyTaxonomyEntry(bFact, RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.OWL.DIFFERENT_FROM.ToString()), aFact).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.API)); } else { //Raise warning event to inform the user: DifferentFrom relation cannot be added to the data because it violates the taxonomy consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("DifferentFrom relation between fact '{0}' and fact '{1}' cannot be added to the data because it violates the taxonomy consistency.", aFact, bFact)); } } return(this); }
/// <summary> /// Adds the "ontologyFact -> datatypeProperty -> ontologyLiteral" relation to the data /// </summary> public RDFOntologyData AddAssertionRelation(RDFOntologyFact ontologyFact, RDFOntologyDatatypeProperty datatypeProperty, RDFOntologyLiteral ontologyLiteral) { if (ontologyFact != null && datatypeProperty != null && ontologyLiteral != null) { //Enforce preliminary check on usage of BASE properties if (!RDFOntologyChecker.CheckReservedProperty(datatypeProperty)) { this.Relations.Assertions.AddEntry(new RDFOntologyTaxonomyEntry(ontologyFact, datatypeProperty, ontologyLiteral)); this.AddLiteral(ontologyLiteral); } else { //Raise warning event to inform the user: Assertion relation cannot be added to the data because usage of BASE reserved properties compromises the taxonomy consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("Assertion relation between fact '{0}' and literal '{1}' cannot be added to the data because usage of BASE reserved properties compromises the taxonomy consistency.", ontologyFact, ontologyLiteral)); } } return(this); }
/// <summary> /// Adds the "aFact -> objectProperty -> bFact" relation to the data /// </summary> public RDFOntologyData AddAssertionRelation(RDFOntologyFact aFact, RDFOntologyObjectProperty objectProperty, RDFOntologyFact bFact) { if (aFact != null && objectProperty != null && bFact != null) { //Enforce taxonomy checks before adding the assertion //Even if legal, we don't permit creation of transitive cycles!! if (!RDFBASEOntologyReasoningHelper.IsTransitiveAssertionOf(bFact, objectProperty, aFact, this)) { this.Relations.Assertions.AddEntry(new RDFOntologyTaxonomyEntry(aFact, objectProperty, bFact)); } else { //Raise warning event to inform the user: Assertion relation cannot be added to the data because it violates the taxonomy transitive consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("Assertion relation between fact '{0}' and fact '{1}' with transitive property '{2}' cannot be added to the data because it would violate the taxonomy consistency (transitive cycle detected).", aFact, bFact, objectProperty)); } } return(this); }
/// <summary> /// Triggers the execution of the given rule on the given ontology. /// Returns a boolean indicating if new evidences have been found. /// </summary> internal Boolean TriggerRule(String ruleName, RDFOntology ontology, RDFOntologyReasoningReport report) { var reasonerRule = this.SelectRule(ruleName); if (reasonerRule != null) { //Raise launching signal RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Launching execution of reasoning rule '{0}'", ruleName)); //Launch the reasoning rule var oldCnt = report.EvidencesCount; reasonerRule.ExecuteRule(ontology, report); var newCnt = report.EvidencesCount - oldCnt; //Raise termination signal RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Completed execution of reasoning rule '{0}': found {1} new evidences", ruleName, newCnt)); return(newCnt > 0); } return(false); }
/// <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> /// Adds the "ontologyFact -> rdf:type -> ontologyClass" relation to the data. /// </summary> public RDFOntologyData AddClassTypeRelation(RDFOntologyFact ontologyFact, RDFOntologyClass ontologyClass) { if (ontologyFact != null && ontologyClass != null) { //Enforce taxonomy checks before adding the classType relation //Only plain classes can be explicitly assigned as classtypes of facts if (!ontologyClass.IsRestrictionClass() && !ontologyClass.IsCompositeClass() && !ontologyClass.IsEnumerateClass() && !ontologyClass.IsDataRangeClass() && //owl:Nothing cannot be assigned as classtype of facts !ontologyClass.Equals(RDFBASEOntology.Instance.Model.ClassModel.SelectClass(RDFVocabulary.OWL.NOTHING.ToString()))) { this.Relations.ClassType.AddEntry(new RDFOntologyTaxonomyEntry(ontologyFact, RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.RDF.TYPE.ToString()), ontologyClass)); } else { //Raise warning event to inform the user: ClassType relation cannot be added to the data because only plain classes can be explicitly assigned as class types of facts RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("ClassType relation between fact '{0}' and class '{1}' cannot be added to the data because only plain classes can be explicitly assigned as class types of facts.", ontologyFact, ontologyClass)); } } return(this); }
/// <summary> /// Adds the given standard annotation to the given ontology fact /// </summary> public RDFOntologyData AddStandardAnnotation(RDFSemanticsEnums.RDFOntologyStandardAnnotation standardAnnotation, RDFOntologyFact ontologyFact, RDFOntologyResource annotationValue) { if (ontologyFact != null && annotationValue != null) { switch (standardAnnotation) { //owl:versionInfo case RDFSemanticsEnums.RDFOntologyStandardAnnotation.VersionInfo: if (annotationValue.IsLiteral()) { this.Annotations.VersionInfo.AddEntry(new RDFOntologyTaxonomyEntry(ontologyFact, RDFVocabulary.OWL.VERSION_INFO.ToRDFOntologyAnnotationProperty(), annotationValue)); } else { RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Cannot annotate ontology fact with owl:versionInfo value '{0}' because it is not an ontology literal", annotationValue)); } break; //owl:versionIRI case RDFSemanticsEnums.RDFOntologyStandardAnnotation.VersionIRI: RDFSemanticsEvents.RaiseSemanticsInfo("Cannot annotate ontology fact with owl:versionIRI because it is reserved for ontologies"); break; //rdfs:comment case RDFSemanticsEnums.RDFOntologyStandardAnnotation.Comment: if (annotationValue.IsLiteral()) { this.Annotations.Comment.AddEntry(new RDFOntologyTaxonomyEntry(ontologyFact, RDFVocabulary.RDFS.COMMENT.ToRDFOntologyAnnotationProperty(), annotationValue)); } else { RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Cannot annotate ontology fact with rdfs:comment value '{0}' because it is not an ontology literal", annotationValue)); } break; //rdfs:label case RDFSemanticsEnums.RDFOntologyStandardAnnotation.Label: if (annotationValue.IsLiteral()) { this.Annotations.Label.AddEntry(new RDFOntologyTaxonomyEntry(ontologyFact, RDFVocabulary.RDFS.LABEL.ToRDFOntologyAnnotationProperty(), annotationValue)); } else { RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Cannot annotate ontology fact with rdfs:label value '{0}' because it is not an ontology literal", annotationValue)); } break; //rdfs:seeAlso case RDFSemanticsEnums.RDFOntologyStandardAnnotation.SeeAlso: this.Annotations.SeeAlso.AddEntry(new RDFOntologyTaxonomyEntry(ontologyFact, RDFVocabulary.RDFS.SEE_ALSO.ToRDFOntologyAnnotationProperty(), annotationValue)); break; //rdfs:isDefinedBy case RDFSemanticsEnums.RDFOntologyStandardAnnotation.IsDefinedBy: this.Annotations.IsDefinedBy.AddEntry(new RDFOntologyTaxonomyEntry(ontologyFact, RDFVocabulary.RDFS.IS_DEFINED_BY.ToRDFOntologyAnnotationProperty(), annotationValue)); break; //owl:priorVersion case RDFSemanticsEnums.RDFOntologyStandardAnnotation.PriorVersion: RDFSemanticsEvents.RaiseSemanticsInfo("Cannot annotate ontology fact with owl:priorVersion because it is reserved for ontologies"); break; //owl:imports case RDFSemanticsEnums.RDFOntologyStandardAnnotation.Imports: RDFSemanticsEvents.RaiseSemanticsInfo("Cannot annotate ontology fact with owl:imports because it is reserved for ontologies"); break; //owl:backwardCompatibleWith case RDFSemanticsEnums.RDFOntologyStandardAnnotation.BackwardCompatibleWith: RDFSemanticsEvents.RaiseSemanticsInfo("Cannot annotate ontology fact with owl:backwardCompatibleWith because it is reserved for ontologies"); break; //owl:incompatibleWith case RDFSemanticsEnums.RDFOntologyStandardAnnotation.IncompatibleWith: RDFSemanticsEvents.RaiseSemanticsInfo("Cannot annotate ontology fact with owl:incompatibleWith because it is reserved for ontologies"); break; } } return(this); }
/// <summary> /// Adds the "ontologyFact -> ontologyAnnotationProperty -> ontologyResource" annotation to the data /// </summary> public RDFOntologyData AddCustomAnnotation(RDFOntologyFact ontologyFact, RDFOntologyAnnotationProperty ontologyAnnotationProperty, RDFOntologyResource ontologyResource) { if (ontologyFact != null && ontologyAnnotationProperty != null && ontologyResource != null) { //owl:versionInfo if (ontologyAnnotationProperty.Equals(RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.OWL.VERSION_INFO.ToString()))) { if (ontologyResource.IsLiteral()) { this.AddVersionInfoAnnotation(ontologyFact, (RDFOntologyLiteral)ontologyResource); } } //vs:term_status else if (ontologyAnnotationProperty.Equals(RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.VS.TERM_STATUS.ToString()))) { //Raise warning event to inform the user: vs:term_status annotation property cannot be used for facts RDFSemanticsEvents.RaiseSemanticsWarning("vs:term_status annotation property cannot be used for facts."); } //rdfs:comment else if (ontologyAnnotationProperty.Equals(RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.RDFS.COMMENT.ToString()))) { if (ontologyResource.IsLiteral()) { this.AddCommentAnnotation(ontologyFact, (RDFOntologyLiteral)ontologyResource); } } //rdfs:label else if (ontologyAnnotationProperty.Equals(RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.RDFS.LABEL.ToString()))) { if (ontologyResource.IsLiteral()) { this.AddLabelAnnotation(ontologyFact, (RDFOntologyLiteral)ontologyResource); } } //rdfs:seeAlso else if (ontologyAnnotationProperty.Equals(RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.RDFS.SEE_ALSO.ToString()))) { this.AddSeeAlsoAnnotation(ontologyFact, ontologyResource); } //rdfs:isDefinedBy else if (ontologyAnnotationProperty.Equals(RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.RDFS.IS_DEFINED_BY.ToString()))) { this.AddIsDefinedByAnnotation(ontologyFact, ontologyResource); } //ontology-specific else if (ontologyAnnotationProperty.Equals(RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.OWL.VERSION_IRI.ToString())) || ontologyAnnotationProperty.Equals(RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.OWL.IMPORTS.ToString())) || ontologyAnnotationProperty.Equals(RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.OWL.BACKWARD_COMPATIBLE_WITH.ToString())) || ontologyAnnotationProperty.Equals(RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.OWL.INCOMPATIBLE_WITH.ToString())) || ontologyAnnotationProperty.Equals(RDFBASEOntology.Instance.Model.PropertyModel.SelectProperty(RDFVocabulary.OWL.PRIOR_VERSION.ToString()))) { //Raise warning event to inform the user: Ontology-specific annotation properties cannot be used for facts RDFSemanticsEvents.RaiseSemanticsWarning("Ontology-specific annotation properties cannot be used for facts."); } //custom else { this.Annotations.CustomAnnotations.AddEntry(new RDFOntologyTaxonomyEntry(ontologyFact, ontologyAnnotationProperty, ontologyResource)); if (ontologyResource.IsLiteral()) { this.AddLiteral((RDFOntologyLiteral)ontologyResource); } } } return(this); }