diff --git a/graph/src/indexer.rs b/graph/src/indexer.rs index 0802af6..c8c69fc 100644 --- a/graph/src/indexer.rs +++ b/graph/src/indexer.rs @@ -123,8 +123,10 @@ impl<'a> Indexer<'a> { } pub async fn ontology(&self, client: &mut OntologyClient) -> crate::Result>> { - let label_filter = self.language.to_filter_expression("label"); - let description_filter = self.language.to_filter_expression("description"); + let filter = LanguageCondition::filter([ + (String::from("label"), self.language.clone()), + (String::from("description"), self.language.clone()), + ]); let mut request = OntologyQueryRequest::default(); request.sparql_query = Some(format!(r#"PREFIX rdf: @@ -135,12 +137,11 @@ SELECT ?class ?subject ?label ?description WHERE {{ VALUES ?class {{ rdf:Property rdfs:Class skos:Concept }} ?subject a ?class ; rdfs:label ?label . - {label_filter} OPTIONAL {{ ?subject rdfs:comment ?comment }} OPTIONAL {{ ?subject skos:definition ?definition }} BIND(COALESCE(?definition, ?comment) AS ?description) - {description_filter} + {filter} }}"#)); let response = client.query(request).await?; diff --git a/graph/src/language.rs b/graph/src/language.rs index ddcbbf2..b8237bc 100644 --- a/graph/src/language.rs +++ b/graph/src/language.rs @@ -1,3 +1,4 @@ +use std::env::var; use oxigraph::model::{Literal, TermRef}; use oxilangtag::LanguageTag; use std::sync::LazyLock; @@ -53,7 +54,7 @@ impl LanguageCondition { } pub fn filter(conditions: impl IntoIterator) -> String { - let exact_expression = |language, variable| Expression::FunctionCall( + let exact_expression = |variable: String, language| Expression::FunctionCall( Function::LangMatches, vec![ Expression::FunctionCall(Function::Lang, vec![ Expression::Variable(Variable::new_unchecked(variable)) @@ -70,10 +71,10 @@ impl LanguageCondition { let condition_to_expression = |variable, condition| match condition { LanguageCondition::ExactMatchOnly(language) => - Some(exact_expression(language.to_string(), variable)), + Some(exact_expression(variable, language.to_string())), LanguageCondition::ExactMatchOrUntagged(language) => { Some(Expression::Or( - Box::new(exact_expression(language.to_string(), variable.clone())), + Box::new(exact_expression(variable.clone(), language.to_string())), Box::new(untagged_expression(variable)), )) } @@ -84,28 +85,15 @@ impl LanguageCondition { let mut iter = conditions.into_iter(); let first_expression = iter.next() .and_then(|(variable, condition)| condition_to_expression(variable, condition)); - let remaining_expressions = iter.filter_map(|(variable, condition)| condition_to_expression(variable, condition)) - .collect::>(); - let concatenated_expressions = if let Some(expression) = first_expression { - if remaining_expressions.is_empty() { - //Expression:: - } - } else { String::default() } - } - - pub fn to_sparql_expression(&self, var: &str) -> String { - let foo = - debug!("Test: {foo}"); - - match self { - LanguageCondition::ExactMatchOnly(language) => { - format!(r#"FILTER(langMATCHES(LANG(?{var}), "{language}"))"#) - } - LanguageCondition::ExactMatchOrUntagged(language) => { - format!(r#"FILTER(langMATCHES(LANG(?{var}), "{language}") || !hasLANG(?{var}))"#) - } - LanguageCondition::UntaggedOnly => format!("FILTER(!hasLANG(?{var}))"), - LanguageCondition::AnyOrNone => "".to_string(), + if let Some(expression) = first_expression { + let expr = iter.filter_map(|(variable, condition)| condition_to_expression(variable, condition)) + .fold(expression, |acc, next_exp| Expression::Or(Box::new(acc), Box::new(next_exp))); + GraphPattern::Filter { + expr, + inner: Box::new(GraphPattern::Bgp { patterns: vec![] }), + }.to_string() + } else { + String::default() } } } diff --git a/graph/src/ontology.rs b/graph/src/ontology.rs index b9834d1..4b1ca04 100644 --- a/graph/src/ontology.rs +++ b/graph/src/ontology.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use oxigraph::io::{RdfFormat, RdfParser, RdfSerializer}; use oxigraph::model::{Graph, NamedNode, Triple, TripleRef}; use oxigraph::sparql::results::{QueryResultsFormat, QueryResultsParser, SliceQueryResultsParserOutput}; +use tracing::debug; use gl_inference::proto::ontology_client::OntologyClient; use gl_inference::proto::OntologyQueryRequest; use gl_inference::tonic::codegen::StdError; @@ -117,8 +118,10 @@ SELECT ?subject ?class WHERE {{ } pub async fn datatypes(&mut self) -> crate::Result> { - let label_filter = self.language.to_filter_expression("label"); - let description_filter = self.language.to_filter_expression("description"); + let filter = LanguageCondition::filter([ + (String::from("label"), self.language.clone()), + (String::from("description"), self.language.clone()), + ]); let mut request = OntologyQueryRequest::default(); request.sparql_query = Some(format!(r#"PREFIX rdf: @@ -128,12 +131,10 @@ PREFIX skos: SELECT ?subject ?label ?description WHERE {{ ?subject a rdfs:Datatype OPTIONAL {{ ?subject rdfs:label ?label }} - {label_filter} - OPTIONAL {{ ?subject rdfs:comment ?comment }} OPTIONAL {{ ?subject skos:definition ?definition }} BIND(COALESCE(?definition, ?comment) AS ?description) - {description_filter} + {filter} }}"#)); let response = self.client.query(request).await?; @@ -167,8 +168,11 @@ SELECT ?subject ?label ?description WHERE {{ } pub async fn resource_description(&mut self, subject: NamedNode) -> crate::Result { - let label_filter = self.language.to_filter_expression("label"); - let description_filter = self.language.to_filter_expression("description"); + let filter = LanguageCondition::filter([ + (String::from("label"), self.language.clone()), + (String::from("description"), self.language.clone()), + ]); + debug!("Filter: {filter}"); let mut request = OntologyQueryRequest::default(); request.sparql_query = Some(format!(r#"PREFIX rdf: @@ -177,12 +181,10 @@ PREFIX skos: SELECT ?label ?description WHERE {{ OPTIONAL {{ {subject} rdfs:label ?label }} - {label_filter} - OPTIONAL {{ {subject} rdfs:comment ?comment }} OPTIONAL {{ {subject} skos:definition ?definition }} BIND(COALESCE(?definition, ?comment) AS ?description) - {description_filter} + {filter} }}"#)); let response = self.client.query(request).await?;