use crate::model::{Ontology, Class, Property, Individual, Axiom, OwlIri};
use crate::OwlError;
use fukurow_store::store::RdfStore;
use std::collections::HashMap;
pub trait OntologyLoader {
fn load_from_store(&self, store: &RdfStore) -> Result<Ontology, OwlError>;
}
pub struct DefaultOntologyLoader;
impl OntologyLoader for DefaultOntologyLoader {
fn load_from_store(&self, store: &RdfStore) -> Result<Ontology, OwlError> {
let mut ontology = Ontology::new();
let rdf_type = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
let rdfs_subclass_of = "http://www.w3.org/2000/01/rdf-schema#subClassOf";
let rdfs_domain = "http://www.w3.org/2000/01/rdf-schema#domain";
let rdfs_range = "http://www.w3.org/2000/01/rdf-schema#range";
let owl_class = "http://www.w3.org/2002/07/owl#Class";
let owl_object_property = "http://www.w3.org/2002/07/owl#ObjectProperty";
let owl_datatype_property = "http://www.w3.org/2002/07/owl#DatatypeProperty";
let owl_named_individual = "http://www.w3.org/2002/07/owl#NamedIndividual";
let owl_subclass_of = "http://www.w3.org/2002/07/owl#subClassOf";
let owl_equivalent_class = "http://www.w3.org/2002/07/owl#equivalentClass";
let owl_disjoint_with = "http://www.w3.org/2002/07/owl#disjointWith";
let owl_sub_property_of = "http://www.w3.org/2002/07/owl#subPropertyOf";
let owl_equivalent_property = "http://www.w3.org/2002/07/owl#equivalentProperty";
let owl_functional_property = "http://www.w3.org/2002/07/owl#FunctionalProperty";
let owl_inverse_functional_property = "http://www.w3.org/2002/07/owl#InverseFunctionalProperty";
let owl_transitive_property = "http://www.w3.org/2002/07/owl#TransitiveProperty";
let owl_symmetric_property = "http://www.w3.org/2002/07/owl#SymmetricProperty";
for stored_triple in store.all_triples().values().flatten() {
let triple = &stored_triple.triple;
if triple.predicate == rdf_type {
match triple.object.as_str() {
x if x == owl_class => {
let class = Class::Named(OwlIri::new(triple.subject.clone()));
ontology.classes.insert(class);
}
x if x == owl_object_property => {
let prop = Property::Object(OwlIri::new(triple.subject.clone()));
ontology.properties.insert(prop);
}
x if x == owl_datatype_property => {
let prop = Property::Data(OwlIri::new(triple.subject.clone()));
ontology.properties.insert(prop);
}
x if x == owl_named_individual => {
let individual = Individual(OwlIri::new(triple.subject.clone()));
ontology.individuals.insert(individual);
}
x if x == owl_functional_property => {
if let Some(prop) = self.find_property_by_iri(&ontology, &triple.subject) {
ontology.add_axiom(Axiom::FunctionalProperty(prop));
}
}
x if x == owl_inverse_functional_property => {
if let Some(prop) = self.find_property_by_iri(&ontology, &triple.subject) {
ontology.add_axiom(Axiom::InverseFunctionalProperty(prop));
}
}
x if x == owl_transitive_property => {
if let Some(prop) = self.find_property_by_iri(&ontology, &triple.subject) {
ontology.add_axiom(Axiom::TransitiveProperty(prop));
}
}
x if x == owl_symmetric_property => {
if let Some(prop) = self.find_property_by_iri(&ontology, &triple.subject) {
ontology.add_axiom(Axiom::SymmetricProperty(prop));
}
}
_ => {
if !triple.object.starts_with("http://www.w3.org/2002/07/owl#") {
let class = Class::Named(OwlIri::new(triple.object.clone()));
let individual = Individual(OwlIri::new(triple.subject.clone()));
ontology.add_axiom(Axiom::ClassAssertion(class, individual));
}
}
}
}
else if triple.predicate == rdfs_subclass_of {
let c1 = Class::Named(OwlIri::new(triple.subject.clone()));
let c2 = Class::Named(OwlIri::new(triple.object.clone()));
ontology.add_axiom(Axiom::SubClassOf(c1, c2));
}
else if triple.predicate == owl_subclass_of {
let c1 = Class::Named(OwlIri::new(triple.subject.clone()));
let c2 = Class::Named(OwlIri::new(triple.object.clone()));
ontology.add_axiom(Axiom::SubClassOf(c1, c2));
}
else if triple.predicate == owl_equivalent_class {
let c1 = Class::Named(OwlIri::new(triple.subject.clone()));
let c2 = Class::Named(OwlIri::new(triple.object.clone()));
ontology.add_axiom(Axiom::SubClassOf(c1.clone(), c2.clone()));
ontology.add_axiom(Axiom::SubClassOf(c2, c1));
}
else if triple.predicate == rdfs_domain {
if let Some(prop) = self.find_property_by_iri(&ontology, &triple.subject) {
if let Property::Object(_) = prop {
let class = Class::Named(OwlIri::new(triple.object.clone()));
ontology.add_axiom(Axiom::ObjectPropertyDomain(prop, class));
}
}
}
else if triple.predicate == rdfs_range {
if let Some(prop) = self.find_property_by_iri(&ontology, &triple.subject) {
if let Property::Object(_) = prop {
let class = Class::Named(OwlIri::new(triple.object.clone()));
ontology.add_axiom(Axiom::ObjectPropertyRange(prop, class));
}
}
}
else {
if let Some(prop) = self.find_property_by_iri(&ontology, &triple.predicate) {
if let Property::Object(_) = prop {
let i1 = Individual(OwlIri::new(triple.subject.clone()));
let i2 = Individual(OwlIri::new(triple.object.clone()));
ontology.add_axiom(Axiom::ObjectPropertyAssertion(prop, i1, i2));
}
}
}
}
Ok(ontology)
}
}
impl DefaultOntologyLoader {
fn find_property_by_iri(&self, ontology: &Ontology, iri: &str) -> Option<Property> {
for prop in &ontology.properties {
match prop {
Property::Object(p_iri) | Property::Data(p_iri) => {
if p_iri.0 == iri {
return Some(prop.clone());
}
}
}
}
None
}
}