rudof-project / rudof

RDF data shapes implementation in Rust
https://rudof-project.github.io
Apache License 2.0
35 stars 3 forks source link

Implement feature to create subsets of RDF graphs that are validated using SHACL #209

Open labra opened 1 day ago

labra commented 1 day ago

Implement a feature like the slurp parameter in ShEx.js which can record the neighbours visited during validation and write them to an RDF builder.

This feature can be used to create RDF subsets based on SHACL schemas.

angelip2303 commented 1 day ago

By introducing something like the snippet below in the store we could have an auxiliary data structure for storing the compliant nodes. The idea would be that, for each constraint, if the subset is some, we can store the corresponding triple.

pub struct Store {
    store: RdfData,
    // TODO: subset: Option<RdfData>,
}

In the snippet below we are modifying the helper function which is called by each constraint and generates the validation report. Just by modifying this, the whole implementation changes. Something that I have noticed is that the evaluator is a bit opaque, as it can be seen, the Result is generated if the condition is true, which should be documented.

fn apply<S: SRDFBasic, I: IterationStrategy<S>>(
    // TODO: store: &S,
    component: &CompiledComponent<S>,
    shape: &CompiledShape<S>,
    value_nodes: &ValueNodes<S>,
    iteration_strategy: I,
    evaluator: impl Fn(&I::Item) -> Result<bool, ConstraintError>,
) -> Result<Vec<ValidationResult>, ConstraintError> {
    let results = iteration_strategy
        .iterate(value_nodes)
        .flat_map(|(focus_node, item)| {
            if let Ok(condition) = evaluator(item) {
                if condition {
                    let focus = S::term_as_object(focus_node);
                    let component = Object::iri(component.into());
                    let severity = S::term_as_object(&shape.severity());
                    let source = Some(S::term_as_object(&shape.id().to_owned()));
                    return Some(
                        ValidationResult::new(focus, component, severity).with_source(source),
                    );
                }
                // TODO: else --> incorporate it to the subset
            }
            None
        })
        .collect();

    Ok(results)
}

With the changes above, we can support SHACL generated subsets.