use crate::ir::OrderValue;
use rudof_rdf::rdf_core::parser::rdf_node_parser::constructors::SingleLiteralPropertyParser;
use rudof_rdf::rdf_core::parser::rdf_node_parser::{ParserExt, RDFNodeParse};
use rudof_rdf::rdf_core::term::literal::{ConcreteLiteral, NumericLiteral};
use rudof_rdf::rdf_core::vocabs::{ShaclVocab, XsdVocab};
use rudof_rdf::rdf_core::{FocusRDF, RDFError};
use rust_decimal::Decimal;
pub(crate) fn order<RDF: FocusRDF>() -> impl RDFNodeParse<RDF, Output = OrderValue> {
SingleLiteralPropertyParser::new(ShaclVocab::sh_order()).flat_map(|lit: RDF::Literal| match lit.try_into() {
Ok(concrete_literal) => parse_order_value(concrete_literal),
Err(_e) => Err(RDFError::ParseFailError {
msg: "Failed to convert literal to concrete literal".to_string(),
}),
})
}
fn parse_order_value(concrete_literal: ConcreteLiteral) -> Result<OrderValue, RDFError> {
match concrete_literal {
ConcreteLiteral::NumericLiteral(NumericLiteral::Integer(i)) => Ok(OrderValue::Integer(i)),
ConcreteLiteral::NumericLiteral(NumericLiteral::Decimal(d)) => Ok(OrderValue::Decimal(d)),
ConcreteLiteral::DatatypeLiteral { lexical_form, datatype } => {
let datatype_iris = datatype.get_iri().map_err(|e| RDFError::ParseFailError {
msg: format!("Failed to get datatype IRI: {}", e),
})?;
if datatype_iris == &XsdVocab::xsd_integer() {
match lexical_form.parse::<i128>() {
Ok(i) => Ok(OrderValue::Integer(i)),
Err(e) => Err(RDFError::ParseFailError {
msg: format!("Failed to parse integer from lexical form '{}': {}", lexical_form, e),
}),
}
} else if datatype_iris == &XsdVocab::xsd_decimal() {
match Decimal::from_str_exact(&lexical_form) {
Ok(d) => Ok(OrderValue::Decimal(d)),
Err(e) => Err(RDFError::ParseFailError {
msg: format!("Failed to parse decimal from lexical form '{}': {}", lexical_form, e),
}),
}
} else {
Err(RDFError::ParseFailError {
msg: format!(
"Value of sh:order must be an integer or a decimal literal. Got datatype {}",
datatype
),
})
}
},
_ => {
tracing::warn!(
"Failed to parse order value from concrete literal: {:?}",
concrete_literal
);
Err(RDFError::ParseFailError {
msg: format!(
"Value of sh:order must be an integer or a decimal literal. Got {}",
concrete_literal
),
})
},
}
}