use horned_owl::model::{
Atom, ClassExpression, DArgument, DataProperty, IArgument, Literal, ObjectProperty,
ObjectPropertyExpression, RcStr, Rule, Variable,
};
use ontologos_core::{EntityId, EntityKind, SwrlAtom, SwrlDArg, SwrlIArg, SwrlRule};
use crate::map::Mapper;
impl Mapper<'_> {
pub(crate) fn map_swrl_rule(&mut self, rule: &Rule<RcStr>) -> Option<SwrlRule> {
let body = rule
.body
.iter()
.filter_map(|atom| self.map_swrl_atom(atom))
.collect::<Vec<_>>();
let head = rule
.head
.iter()
.filter_map(|atom| self.map_swrl_atom(atom))
.collect::<Vec<_>>();
if body.len() != rule.body.len() || head.len() != rule.head.len() {
return None;
}
Some(SwrlRule { body, head })
}
fn map_swrl_atom(&mut self, atom: &Atom<RcStr>) -> Option<SwrlAtom> {
match atom {
Atom::ClassAtom { pred, arg } => {
let class = self.named_class_entity(pred)?;
let arg = self.map_iarg(arg)?;
Some(SwrlAtom::Class { class, arg })
}
Atom::ObjectPropertyAtom { pred, args } => {
let property = self.object_property_entity(pred)?;
let subject = self.map_iarg(&args.0)?;
let object = self.map_iarg(&args.1)?;
Some(SwrlAtom::ObjectProperty {
property,
subject,
object,
})
}
Atom::DataPropertyAtom { pred, args } => {
let property = self.data_property_entity(pred)?;
let subject = self.map_darg_as_individual(&args.0)?;
let value = self.map_darg(&args.1)?;
Some(SwrlAtom::DataProperty {
property,
subject,
value,
})
}
Atom::SameIndividualAtom(a, b) => Some(SwrlAtom::SameIndividual(
self.map_iarg(a)?,
self.map_iarg(b)?,
)),
Atom::DifferentIndividualsAtom(a, b) => Some(SwrlAtom::DifferentIndividuals(
self.map_iarg(a)?,
self.map_iarg(b)?,
)),
Atom::DataRangeAtom { pred, arg } => {
let range = self.map_data_range(pred)?;
let arg = self.map_darg(arg)?;
Some(SwrlAtom::DataRange { range, arg })
}
Atom::BuiltInAtom { .. } => None,
}
}
fn map_iarg(&mut self, arg: &IArgument<RcStr>) -> Option<SwrlIArg> {
match arg {
IArgument::Individual(ind) => self.map_individual_entity(ind).map(SwrlIArg::Individual),
IArgument::Variable(var) => Some(SwrlIArg::Variable(variable_name(var))),
}
}
fn map_darg(&mut self, arg: &DArgument<RcStr>) -> Option<SwrlDArg> {
match arg {
DArgument::Variable(var) => Some(SwrlDArg::Variable(variable_name(var))),
DArgument::Literal(lit) => {
let (lexical, datatype) = literal_parts(lit);
let datatype =
datatype.and_then(|dt| self.register_or_warn_entity(dt, EntityKind::Datatype));
Some(SwrlDArg::Literal { lexical, datatype })
}
}
}
fn map_darg_as_individual(&mut self, arg: &DArgument<RcStr>) -> Option<SwrlIArg> {
match arg {
DArgument::Variable(var) => Some(SwrlIArg::Variable(variable_name(var))),
DArgument::Literal(_) => None,
}
}
fn named_class_entity(&mut self, ce: &ClassExpression<RcStr>) -> Option<EntityId> {
let ClassExpression::Class(class) = ce else {
return None;
};
self.register_or_warn_entity(class.as_ref(), EntityKind::Class)
}
fn object_property_entity(
&mut self,
ope: &ObjectPropertyExpression<RcStr>,
) -> Option<EntityId> {
let ObjectPropertyExpression::ObjectProperty(ObjectProperty(prop)) = ope else {
return None;
};
self.register_or_warn_entity(prop.as_ref(), EntityKind::ObjectProperty)
}
fn data_property_entity(&mut self, dp: &DataProperty<RcStr>) -> Option<EntityId> {
self.register_or_warn_entity(dp.as_ref(), EntityKind::DataProperty)
}
}
fn variable_name(var: &Variable<RcStr>) -> String {
local_name(var.as_ref())
}
fn local_name(iri: &str) -> String {
iri.rsplit(['#', '/']).next().unwrap_or(iri).to_owned()
}
fn literal_parts(lit: &Literal<RcStr>) -> (String, Option<&str>) {
match lit {
Literal::Simple { literal } => (literal.clone(), None),
Literal::Language { literal, .. } => (literal.clone(), None),
Literal::Datatype {
literal,
datatype_iri,
} => (literal.clone(), Some(datatype_iri.as_ref())),
}
}