swls_lang_turtle/
prefix.rs1use std::{borrow::Cow, collections::HashMap};
2
3use swls_core::{lsp_types::Url, prelude::*, util::fs::File};
4
5use swls_lang_rdf_base::traits::{NamedNodeExt, Turtle, TurtleExt};
6
7pub async fn find(location: &str, fs: &Fs, client: &impl Client) -> Option<Vec<(String, Url)>> {
11 if location.starts_with("http") {
12 let url = Url::parse(location).ok()?;
13 let content = client
14 .fetch(
15 &location,
16 &HashMap::from([(String::from("Accept"), String::from("text/turtle"))]),
17 )
18 .await
19 .ok()?
20 .body;
21 Some(vec![(content, url)])
22 } else {
23 if let Ok(url) = Url::parse(&location) {
24 let content = fs.0.read_file(&url).await?;
25 Some(vec![(content, url)])
26 } else {
27 let files = fs.0.glob_read(&location).await?;
28 Some(
29 files
30 .into_iter()
31 .flat_map(|File { content, name }| {
32 file_name_to_url(&name).map(|url| (content, url))
33 })
34 .collect(),
35 )
36 }
37 }
38}
39
40#[cfg(not(target_arch = "wasm32"))]
41pub fn file_name_to_url(name: &str) -> Option<Url> {
42 swls_core::lsp_types::Url::from_file_path(name).ok()
43}
44
45#[cfg(target_arch = "wasm32")]
46pub fn file_name_to_url(_name: &str) -> Option<Url> {
47 None
48}
49
50pub fn prefix_from_url(url: &Url) -> Option<(Cow<'static, str>, Cow<'static, str>)> {
51 let segments = url.path_segments()?;
52 let last = segments.last()?;
53
54 let prefix = last.rsplit_once('.').map(|(x, _)| x).unwrap_or(last);
55 let prefix: Cow<'static, str> = Cow::Owned(prefix.to_string());
56
57 let url = Cow::Owned(url.to_string());
58
59 Some((prefix, url))
60}
61
62pub fn prefix_from_declaration(
63 turtle: &Triples2<'_>,
64) -> Option<(Cow<'static, str>, Cow<'static, str>)> {
65 let subject = turtle
66 .iter()
67 .find(|t| {
68 t.predicate.as_str() == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
69 && t.object.as_str() == "http://www.w3.org/2002/07/owl#Ontology"
70 })?
71 .subject
72 .to_owned();
73
74 let prefix = turtle
75 .iter()
76 .find(|t| {
77 t.subject.eq(&subject)
78 && t.predicate.as_str() == "http://purl.org/vocab/vann/preferredNamespacePrefix"
79 })?
80 .object
81 .as_str();
82 let prefix = Cow::Owned(String::from(prefix));
83
84 let url = turtle
85 .iter()
86 .find(|t| {
87 t.subject.eq(&subject)
88 && t.predicate.as_str() == "http://purl.org/vocab/vann/preferredNamespaceUri"
89 })?
90 .object
91 .as_str();
92 let url = Cow::Owned(String::from(url));
93
94 Some((prefix, url))
95}
96
97pub fn prefix_from_prefixes(
98 model: &Turtle,
99 turtle: &Triples2<'_>,
100) -> Option<(Cow<'static, str>, Cow<'static, str>)> {
101 let shortened: Vec<_> = turtle
102 .iter()
103 .filter(|x| x.predicate.as_str() == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
104 .flat_map(|t| model.shorten(t.subject.as_str()))
105 .collect();
106
107 let mut counts = HashMap::new();
108 for short in &shortened {
109 if let Some((prefix, _)) = short.split_once(':') {
110 let key: &mut usize = counts.entry(prefix).or_default();
111 *key += 1;
112 }
113 }
114
115 let (prefix, _) = counts.into_iter().max_by_key(|(_, e)| *e)?;
116
117 let prefix = model
118 .prefixes
119 .iter()
120 .find(|p| p.prefix.as_str() == prefix)?;
121
122 Some((
123 Cow::Owned(String::from(prefix.prefix.as_str())),
124 Cow::Owned(prefix.value.0.expand(model)?),
125 ))
126}
127
128pub fn prefix_from_source(
129 url: &Url,
130 source: &str,
131) -> Option<(Cow<'static, str>, Cow<'static, str>)> {
132 use crate::lang::parser::parse_new;
133 let (turtle, _, _, _, _) = parse_new(source, url.as_str(), None);
134
135 let triples = turtle.get_simple_triples().ok()?;
136
137 prefix_from_declaration(&triples).or_else(|| prefix_from_prefixes(&turtle, &triples))
138}