use crate::render::unescape_manchester_rendering;
use regex::Regex;
use std::cmp::Ordering;
pub const ELLIPSIS: &str = "\u{2026}";
pub fn abbreviate_string(s: &str, max_len: usize) -> String {
if s.is_empty() {
return String::new();
}
if max_len == 0 {
return ELLIPSIS.to_string();
}
let chars: Vec<char> = s.chars().collect();
if chars.len() <= max_len {
return s.to_string();
}
chars.into_iter().take(max_len).collect::<String>() + ELLIPSIS
}
pub fn format_iso8601_utc(
year: u32,
month: u32,
day: u32,
hour: u32,
minute: u32,
second: u32,
) -> String {
format!("{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}Z")
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LexicalLiteral {
pub lexical: String,
pub lang: Option<String>,
pub datatype: Option<String>,
}
pub fn replace_lexical_value(
lexical: &str,
lang: Option<&str>,
datatype: Option<&str>,
pattern: &Regex,
replacement: &str,
) -> LexicalLiteral {
let new_lexical = pattern.replace_all(lexical, replacement).into_owned();
LexicalLiteral {
lexical: new_lexical,
lang: lang.map(str::to_string),
datatype: if lang.is_some() { None } else { datatype.map(str::to_string) },
}
}
pub fn replace_lexical_value_whole(
lexical: &str,
lang: Option<&str>,
datatype: Option<&str>,
replacement: &str,
) -> LexicalLiteral {
let re = Regex::new(r"(?s)^.*$").expect("whole-string pattern");
replace_lexical_value(lexical, lang, datatype, &re, replacement)
}
pub fn render_entity_markdown(display_name: &str, iri: &str) -> String {
let name = unescape_manchester_rendering(display_name);
format!("[{name}]({iri})")
}
pub const DEFAULT_ANNOTATION_PROPERTY_ORDER: &[&str] = &[
"http://www.w3.org/2000/01/rdf-schema#label",
"http://www.w3.org/2004/02/skos/core#prefLabel",
"http://purl.org/dc/elements/1.1/title",
"http://www.geneontology.org/formats/oboInOwl#id",
"http://www.geneontology.org/formats/oboInOwl#hasAlternativeId",
"http://www.geneontology.org/formats/oboInOwl#hasOBONamespace",
"http://purl.obolibrary.org/obo/IAO_0000115",
"http://www.w3.org/2004/02/skos/core#definition",
"http://www.w3.org/2004/02/skos/core#note",
"http://purl.org/dc/elements/1.1/description",
"http://purl.org/dc/elements/1.1/rights",
"http://purl.org/dc/terms/license",
"http://purl.org/dc/elements/1.1/publisher",
"http://purl.org/dc/elements/1.1/creator",
"http://purl.org/dc/elements/1.1/contributor",
"http://www.w3.org/2000/01/rdf-schema#comment",
"http://www.w3.org/2004/02/skos/core#altLabel",
"http://www.w3.org/2000/01/rdf-schema#seeAlso",
"http://www.w3.org/2000/01/rdf-schema#isDefinedBy",
"http://www.geneontology.org/formats/oboInOwl#hasExactSynonym",
"http://www.geneontology.org/formats/oboInOwl#hasRelatedSynonym",
"http://www.geneontology.org/formats/oboInOwl#hasBroadSynonym",
"http://www.geneontology.org/formats/oboInOwl#hasNarrowSynonym",
];
fn annotation_order_index(iri: &str) -> Option<usize> {
DEFAULT_ANNOTATION_PROPERTY_ORDER.iter().position(|&known| known == iri)
}
pub fn cmp_annotation_property_iri(a: &str, b: &str) -> Ordering {
match (annotation_order_index(a), annotation_order_index(b)) {
(Some(i), Some(j)) => i.cmp(&j).then_with(|| a.cmp(b)),
(Some(_), None) => Ordering::Less,
(None, Some(_)) => Ordering::Greater,
(None, None) => a.cmp(b),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn abbreviate_edges() {
assert_eq!(abbreviate_string("", 5), "");
assert_eq!(abbreviate_string("abc", 0), ELLIPSIS);
assert_eq!(abbreviate_string("hello", 5), "hello");
assert_eq!(abbreviate_string("hello", 3), format!("hel{ELLIPSIS}"));
}
#[test]
fn iso8601_format() {
assert_eq!(format_iso8601_utc(2015, 11, 20, 12, 0, 0), "2015-11-20T12:00:00Z");
}
#[test]
fn lexical_replace_preserves_lang() {
let re = Regex::new("world").unwrap();
let lit = replace_lexical_value("hello world", Some("en"), None, &re, "there");
assert_eq!(lit.lexical, "hello there");
assert_eq!(lit.lang.as_deref(), Some("en"));
assert!(lit.datatype.is_none());
}
#[test]
fn markdown_unescapes_manchester() {
assert_eq!(
render_entity_markdown("'has part'", "http://ex.org#hp"),
"[has part](http://ex.org#hp)"
);
}
#[test]
fn annotation_order_labels_before_comments() {
assert_eq!(
cmp_annotation_property_iri(
"http://www.w3.org/2000/01/rdf-schema#label",
"http://www.w3.org/2000/01/rdf-schema#comment"
),
Ordering::Less
);
}
}