stam-tools 0.15.3

Command-line tools for working with stand-off annotations on text (STAM)
Documentation
use crate::align::print_transposition;
use stam::*;

pub fn transpose<'store>(
    store: &'store mut AnnotationStore,
    mut transposition_queries: Vec<Query<'store>>,
    queries: Vec<Query<'store>>,
    use_transposition_var: Option<&str>,
    use_var: Option<&str>,
    id_prefix: Option<String>,
    idstrategy: IdStrategy,
    ignore_errors: bool,
    verbose: bool,
    config: TransposeConfig,
) -> Result<Vec<AnnotationHandle>, StamError> {
    let mut builders = Vec::new();
    while transposition_queries.len() < queries.len() {
        let query = transposition_queries
            .get(transposition_queries.len() - 1)
            .expect("there must be transposition queries");
        transposition_queries.push(query.clone());
    }
    for (transposition_query, query) in transposition_queries.into_iter().zip(queries.into_iter()) {
        let iter = store.query(transposition_query)?;
        let mut transposition: Option<ResultItem<Annotation>> = None;
        let transpositiondata = store
            .find_data(
                "https://w3id.org/stam/extensions/stam-transpose/",
                "Transposition",
                DataOperator::Null,
            )
            .next()
            .ok_or_else(|| {
                StamError::OtherError(
                    "No transpositions at all were found in the annotation store (the STAM Transpose vocabulary is not present in the store)",
                )
            })?;
        for resultrow in iter {
            if let Ok(QueryResultItem::Annotation(annotation)) =
                resultrow.get_by_name_or_last(use_transposition_var)
            {
                if !annotation.has_data(&transpositiondata) {
                    return Err(StamError::OtherError(
                        "The retrieved annotation is not explicitly marked as a Transposition, refusing to use",
                    ));
                }
                transposition = Some(annotation.clone());
                break;
            }
        }
        if let Some(transposition) = transposition {
            let iter = store.query(query)?;
            for resultrow in iter {
                if let Ok(QueryResultItem::Annotation(annotation)) =
                    resultrow.get_by_name_or_last(use_var)
                {
                    let mut config = config.clone();
                    if let Some(id) = annotation.id() {
                        let randomid = generate_id("", "");
                        config.transposition_id = if let Some(id_prefix) = &id_prefix {
                            Some(format!("{}{}-transposition-{}", id_prefix, id, randomid))
                        } else {
                            Some(format!("{}-transposition-{}", id, randomid))
                        };
                        config.resegmentation_id = if let Some(id_prefix) = &id_prefix {
                            Some(format!("{}{}-resegmentation-{}", id_prefix, id, randomid))
                        } else {
                            Some(format!("{}-resegmentation-{}", id, randomid))
                        };
                        config.source_side_id = Some(id.to_string());
                        config.existing_source_side = true;
                        config.target_side_ids = vec![if let Some(id_prefix) = &id_prefix {
                            format!("{}{}", id_prefix, regenerate_id(id, &idstrategy))
                        } else {
                            regenerate_id(id, &idstrategy)
                        }];
                    } else {
                        config.existing_source_side = false;
                    }
                    match annotation.transpose(&transposition, config) {
                        Ok(results) => builders.extend(results),
                        Err(StamError::NoText(_)) => {
                            eprintln!(
                                "WARNING: Skipping transposition of annotation that references no text: {}",
                                annotation.id().unwrap_or("(no id)"),
                            );
                        }
                        Err(err) => {
                            eprintln!(
                                "WARNING: Failed to transpose annotation {}: {}",
                                annotation.id().unwrap_or("(no id)"),
                                err
                            );
                            if !ignore_errors {
                                return Err(StamError::OtherError(
                                    "Failed to transpose annotation",
                                ));
                            }
                        }
                    }
                } else {
                    return Err(StamError::OtherError(
                            "Query should return instances of ANNOTATION to transpose, got something else instead",
                        ));
                }
            }
        } else {
            return Err(StamError::OtherError(
                "First query should return an ANNOTATION that is a transposition, none found",
            ));
        }
    }
    let mut annotations = Vec::with_capacity(builders.len());
    for builder in builders {
        let annotation_handle = store.annotate(builder)?;
        annotations.push(annotation_handle);
        if verbose {
            let annotation = store
                .annotation(annotation_handle)
                .expect("annotation was just added");
            let transpositiondata = store
                .find_data(
                    "https://w3id.org/stam/extensions/stam-transpose/",
                    "Transposition",
                    DataOperator::Null,
                )
                .next()
                .ok_or_else(|| {
                    StamError::OtherError(
                        "No transpositions at all were found in the annotation store (the STAM Transpose vocabulary is not present in the store)",
                    )
                })?;
            if annotation.has_data(&transpositiondata) {
                print_transposition(&annotation);
            } else {
                eprintln!(
                    "# added annotation {}",
                    annotation.id().expect("annotation must have ID")
                );
            }
        }
    }
    eprintln!("{} annotations(s) created", annotations.len());
    Ok(annotations)
}