//! SHACL RDF
//!
//! Converts between SHACl AST and RDF
//!
#![deny(rust_2018_idioms)]

pub mod error;
mod rdf_to_shacl;
mod shacl_to_rdf;

pub use rdf_to_shacl::ShaclParser;
use rudof_rdf::rdf_core::FocusRDF;
pub use shacl_to_rdf::ShaclWriter;

pub fn parse_shacl_rdf<RDF>(rdf: RDF) -> Result<shacl_ast::ShaclSchema<RDF>, error::ShaclParserError>
where
    RDF: FocusRDF,
{
    let mut parser = ShaclParser::new(rdf);
    let schema = parser.parse()?;
    Ok(schema)
}

#[cfg(test)]
mod tests {
    use super::*;
    use iri_s::iri;
    use rudof_rdf::rdf_core::{RDFFormat, term::Object};
    use rudof_rdf::rdf_impl::{InMemoryGraph, ReaderMode};
    use shacl_ast::node_shape::NodeShape;
    use shacl_ast::shape::Shape;
    use shacl_ast::target::Target;

    #[test]
    fn test_parse_shacl_rdf() {
        let graph = r#"
            @prefix sh: <http://www.w3.org/ns/shacl#> .
            @prefix : <http://example.org/> .

            :Shape a sh:NodeShape ;
                sh:targetClass :TargetClass .
        "#;

        let rdf = InMemoryGraph::from_str(graph, &RDFFormat::Turtle, None, &ReaderMode::Strict).unwrap();
        let schema = parse_shacl_rdf(rdf).unwrap();
        let shape = schema
            .get_shape(&Object::iri(iri!("http://example.org/Shape")))
            .unwrap();
        let expected_node_shape =
            NodeShape::new(Object::iri(iri!("http://example.org/Shape"))).with_targets(vec![Target::target_class(
                Object::iri(iri!("http://example.org/TargetClass")),
            )]);
        let expected_shape = Shape::node_shape(expected_node_shape);
        assert_eq!(*shape, expected_shape);
    }
}
