Skip to content

Commit

Permalink
Add support for SWRL rules
Browse files Browse the repository at this point in the history
  • Loading branch information
ckindermann committed Dec 6, 2024
1 parent caf6d2b commit 04c2e02
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 36 deletions.
25 changes: 25 additions & 0 deletions src/ofn_2_ldtab/axiom_translation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::ofn_2_ldtab::annotation_translation;
use crate::ofn_2_ldtab::class_translation;
use crate::ofn_2_ldtab::property_translation;
use crate::ofn_2_ldtab::rule_translation;
use crate::ofn_2_ldtab::util;
use rand::Rng;
use serde_json::json;
Expand Down Expand Up @@ -1071,6 +1072,30 @@ pub fn translate_annotation_assertion_axiom(v: &Value) -> Value {
}
}

pub fn translate_rule(v: &Value) -> Value {

let owl = annotation_translation::get_owl(v);
let ofn_annotations = annotation_translation::get_annotations(v);
let annotation = annotation_translation::translate_annotations(&ofn_annotations);

let body = rule_translation::translate(&owl[1]);
let head = rule_translation::translate(&owl[2]);

//subject is a blank node (that needs to be a hash of the rule)

let triple = json!({
"assertion":"1",
"retraction":"0",
"graph":"graph",
"subject":"_:gen",
"predicate":"owl:versionIRI",
"object":body,
"datatype":"_IRI",
"annotation": annotation //NOTE: this deviates from ldtab.clj
});
triple
}

pub fn translate_ontology(v: &Value) -> Value {
let iri = &v[1];
let viri = &v[2];
Expand Down
5 changes: 3 additions & 2 deletions src/ofn_2_ldtab/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod util;
pub mod annotation_translation;
pub mod axiom_translation;
pub mod class_translation;
pub mod rule_translation;
pub mod property_translation;
pub mod annotation_translation;
pub mod translation;
pub mod util;
104 changes: 104 additions & 0 deletions src/ofn_2_ldtab/rule_translation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use crate::ofn_2_ldtab::util;
use crate::ofn_2_ldtab::property_translation;
use crate::ofn_2_ldtab::class_translation;
use serde_json::json;
use serde_json::{Map, Value};


pub fn translate(v: &Value) -> Value {
match v[0].as_str() {
Some("Body") => translate_body(v),
Some("Head") => translate_head(v),
Some("ObjectPropertyAtom") => translate_object_property_atom(v),
Some(_) => json!("TODO"),
//None => owl::OWL::Named(String::from(v.as_str().unwrap())),

//Some("Variable") => axiom_translation::translate_ontology(v),
//Some("SameIndividualAtom") => axiom_translation::translate_ontology(v),
//Some("DifferentIndividualsAtom") => axiom_translation::translate_ontology(v),
//Some("DataRangeAtom") => axiom_translation::translate_ontology(v),
//Some("ClassAtom") => axiom_translation::translate_ontology(v),
//Some("BuiltInAtom") => axiom_translation::translate_ontology(v),
//
None => translate_named_entity(&v),
}
}

pub fn translate_named_entity(v: &Value) -> Value {
let o: String = String::from(v.as_str().unwrap());
json!(o)
}

pub fn get_object(v: &Value) -> Value {
let o: Value = translate(&v);
let d: String = String::from(util::translate_datatype(&v).as_str().unwrap());

json!({"object" : o,
"datatype" : d})
}

pub fn translate_object_property_atom(v: &Value) -> Value {
let type_o = get_object(&json!("swrl:IndividualPropertyAtom"));
let property_o = get_object(&v[1]);
let arg1_o = get_object(&v[2]);
let arg2_o = get_object(&v[3]);
json!( {"datatype" : "_JSON",
"object": vec![json!({"rdf:type" : vec![type_o],
"swrl:propertyPredicate" : vec![property_o],
"swrl:argument1" : vec![arg1_o],
"swrl:argument2" : vec![arg2_o]})]})
}

pub fn translate_body(v: &Value) -> Value {

let array = v.as_array().unwrap();
let args = array[1..].to_vec();

let mut map = Map::new();

for arg in args.iter().rev() {
if map.is_empty() { //first element
let rest_o: Value = get_object(&json!("rdf:nil"));
let type_o: Value = get_object(&json!("swrl:AtomList"));
map.insert(String::from("rdf:rest"),json!(vec![rest_o]));
map.insert(String::from("rdf:type"),json!(vec![type_o]));
map.insert(String::from("rdf:first"),json!(vec![translate(arg)]));
} else {
let inner = map.clone();
map.clear();
let type_o: Value = get_object(&json!("swrl:AtomList"));
map.insert(String::from("rdf:type"),json!(vec![type_o]));
map.insert(String::from("rdf:first"),json!(vec![translate(arg)]));
map.insert(String::from("rdf:rest"),json!(vec![json!(inner)]));
}
}

json!({"swrl:body" : vec![map]})
}

pub fn translate_head(v: &Value) -> Value {

let array = v.as_array().unwrap();
let args = array[1..].to_vec();

let mut map = Map::new();

for arg in args.iter().rev() {
if map.is_empty() { //first element
let rest_o: Value = get_object(&json!("rdf:nil"));
let type_o: Value = get_object(&json!("swrl:AtomList"));
map.insert(String::from("rdf:rest"),json!(vec![rest_o]));
map.insert(String::from("rdf:type"),json!(vec![type_o]));
map.insert(String::from("rdf:first"),json!(vec![translate(arg)]));
} else {
let inner = map.clone();
map.clear();
let type_o: Value = get_object(&json!("swrl:AtomList"));
map.insert(String::from("rdf:type"),json!(vec![type_o]));
map.insert(String::from("rdf:first"),json!(vec![translate(arg)]));
map.insert(String::from("rdf:rest"),json!(vec![json!(inner)]));
}
}

json!({"swrl:head" : vec![map]})
}
104 changes: 70 additions & 34 deletions src/ofn_2_ldtab/translation.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
use serde_json::{Value};
use crate::ofn_2_ldtab::axiom_translation as axiom_translation;
use crate::ofn_2_ldtab::util as util;

use crate::ofn_2_ldtab::axiom_translation;
use crate::ofn_2_ldtab::util;
use serde_json::Value;

/// Given an OFN S-expression (encoded in JSON),
/// return its corresponding LDTab ThickTripe
///
/// Examples
///
/// let ofn_string = r#"["SubClassOf","obo:IAO_0000120",["ObjectSomeValuesFrom","obo:BFO_0000050","obo:OBI_0500000"]]"#;
/// let ofn_string = r#"["SubClassOf","obo:IAO_0000120",["ObjectSomeValuesFrom","obo:BFO_0000050","obo:OBI_0500000"]]"#;
/// let ofn = util::parser::parse(&ofn_string);
/// let thick_triple = ofn_2_ldtab::translation::ofn_2_thick_triple(&ofn);
/// println!("{}", thick_triple);
///
pub fn ofn_2_thick_triple(v : &Value) -> Value {

/// println!("{}", thick_triple);
///
pub fn ofn_2_thick_triple(v: &Value) -> Value {
let ldtab_triple = match v[0].as_str() {
Some("Declaration") => axiom_translation::translate_declaration(v),
Some("DatatypeDefinition") => axiom_translation::translate_datatype_definition(v),
Expand All @@ -24,20 +22,42 @@ pub fn ofn_2_thick_triple(v : &Value) -> Value {
Some("EquivalentClasses") => axiom_translation::translate_equivalent_classes_axiom(v),
Some("SubObjectPropertyOf") => axiom_translation::translate_sub_object_property(v),
Some("SubDataPropertyOf") => axiom_translation::translate_sub_data_property(v),
Some("EquivalentObjectProperties") => axiom_translation::translate_equivalent_properties_axiom(v),
Some("EquivalentDataProperties") => axiom_translation::translate_equivalent_properties_axiom(v),
Some("DisjointObjectProperties") => axiom_translation::translate_disjoint_properties_axiom(v),
Some("DisjointDataProperties") => axiom_translation::translate_disjoint_properties_axiom(v),
Some("InverseObjectProperties") => axiom_translation::translate_inverse_properties_axiom(v),
Some("FunctionalObjectProperty") => axiom_translation::translate_functional_property_axiom(v),
Some("FunctionalDataProperty") => axiom_translation::translate_functional_property_axiom(v),
Some("InverseFunctionalObjectProperty") => axiom_translation::translate_inverse_functional_object_property_axiom(v),
Some("ReflexiveObjectProperty") => axiom_translation::translate_reflexive_object_property_axiom(v),
Some("IrreflexiveObjectProperty") => axiom_translation::translate_irreflexive_object_property_axiom(v),
Some("SymmetricObjectProperty") => axiom_translation::translate_symmetric_object_property_axiom(v),
Some("AsymmetricObjectProperty") => axiom_translation::translate_asymmetric_object_property_axiom(v),
Some("TransitiveObjectProperty") => axiom_translation::translate_transitive_object_property_axiom(v),
Some("ObjectPropertyDomain") => axiom_translation::translate_object_property_domain_axiom(v),
Some("EquivalentObjectProperties") => {
axiom_translation::translate_equivalent_properties_axiom(v)
}
Some("EquivalentDataProperties") => {
axiom_translation::translate_equivalent_properties_axiom(v)
}
Some("DisjointObjectProperties") => {
axiom_translation::translate_disjoint_properties_axiom(v)
}
Some("DisjointDataProperties") => axiom_translation::translate_disjoint_properties_axiom(v),
Some("InverseObjectProperties") => axiom_translation::translate_inverse_properties_axiom(v),
Some("FunctionalObjectProperty") => {
axiom_translation::translate_functional_property_axiom(v)
}
Some("FunctionalDataProperty") => axiom_translation::translate_functional_property_axiom(v),
Some("InverseFunctionalObjectProperty") => {
axiom_translation::translate_inverse_functional_object_property_axiom(v)
}
Some("ReflexiveObjectProperty") => {
axiom_translation::translate_reflexive_object_property_axiom(v)
}
Some("IrreflexiveObjectProperty") => {
axiom_translation::translate_irreflexive_object_property_axiom(v)
}
Some("SymmetricObjectProperty") => {
axiom_translation::translate_symmetric_object_property_axiom(v)
}
Some("AsymmetricObjectProperty") => {
axiom_translation::translate_asymmetric_object_property_axiom(v)
}
Some("TransitiveObjectProperty") => {
axiom_translation::translate_transitive_object_property_axiom(v)
}
Some("ObjectPropertyDomain") => {
axiom_translation::translate_object_property_domain_axiom(v)
}
Some("ObjectPropertyRange") => axiom_translation::translate_object_property_range_axiom(v),

Some("DataPropertyDomain") => axiom_translation::translate_data_property_domain_axiom(v),
Expand All @@ -46,25 +66,41 @@ pub fn ofn_2_thick_triple(v : &Value) -> Value {
Some("DifferentIndividuals") => axiom_translation::translate_different_individuals_axiom(v),
Some("HasKey") => axiom_translation::translate_has_key_axiom(v),
Some("ClassAssertion") => axiom_translation::translate_class_assertion_axiom(v),
Some("ObjectPropertyAssertion") => axiom_translation::translate_object_property_assertion_axiom(v),
Some("NegativeObjectPropertyAssertion") => axiom_translation::translate_negative_object_property_assertion_axiom(v),
Some("DataPropertyAssertion") => axiom_translation::translate_object_property_assertion_axiom(v),
Some("NegativeDataPropertyAssertion") => axiom_translation::translate_negative_data_property_assertion_axiom(v),
Some("ObjectPropertyAssertion") => {
axiom_translation::translate_object_property_assertion_axiom(v)
}
Some("NegativeObjectPropertyAssertion") => {
axiom_translation::translate_negative_object_property_assertion_axiom(v)
}
Some("DataPropertyAssertion") => {
axiom_translation::translate_object_property_assertion_axiom(v)
}
Some("NegativeDataPropertyAssertion") => {
axiom_translation::translate_negative_data_property_assertion_axiom(v)
}
Some("AnnotationAssertion") => axiom_translation::translate_annotation_assertion_axiom(v),
Some("SubAnnotationPropertyOf") => axiom_translation::translate_sub_annotation_property_of_axiom(v),
Some("AnnotationPropertyDomain") => axiom_translation::translate_annotation_property_domain_axiom(v),
Some("AnnotationPropertyRange") => axiom_translation::translate_annotation_property_range_axiom(v),
Some("SubAnnotationPropertyOf") => {
axiom_translation::translate_sub_annotation_property_of_axiom(v)
}
Some("AnnotationPropertyDomain") => {
axiom_translation::translate_annotation_property_domain_axiom(v)
}
Some("AnnotationPropertyRange") => {
axiom_translation::translate_annotation_property_range_axiom(v)
}
Some("Import") => axiom_translation::translate_ontology_import(v),

//TODO: ontology annotations
Some("OntologyAnnotation") => axiom_translation::translate_ontology_annotation(v),
Some("DocIRI") => axiom_translation::translate_doc_iri(v),
Some("Ontology") => axiom_translation::translate_ontology(v),
Some("OntologyAnnotation") => axiom_translation::translate_ontology_annotation(v),
Some("DocIRI") => axiom_translation::translate_doc_iri(v),//this is horned-owl specific
Some("Ontology") => axiom_translation::translate_ontology(v),

Some("DLSafeRule") => axiom_translation::translate_rule(v),

Some(_) => panic!(),
None => panic!(),
};

//ensure that all triples for LDTab conform to the same order
util::sort_value(&ldtab_triple)
util::sort_value(&ldtab_triple)
}

0 comments on commit 04c2e02

Please sign in to comment.