1
pub(crate) mod index_path;
2

            
3
use self::index_path::IndexPath;
4
use crate::server_error::MyError;
5
use sophia::{
6
    api::{
7
        graph::MutableGraph,
8
        ns::{rdf::type_, Namespace},
9
        parser::TripleParser,
10
        serializer::{Stringifier, TripleSerializer},
11
        source::TripleSource,
12
        triple::Triple,
13
    },
14
    inmem::graph::LightGraph,
15
    iri::Iri,
16
    turtle::{parser::turtle::TurtleParser, serializer::turtle::TurtleSerializer},
17
};
18
use std::{error::Error, path::Path};
19

            
20
6
#[derive(PartialEq, Eq, PartialOrd, Ord)]
21
pub struct IndexEntry {
22
    pub name: String,
23
    pub base_uri: Option<String>,
24
}
25

            
26
/**
27
 * Read an index.ttl file and return the entries that are mentioned in it.
28
 */
29
11
pub(crate) fn read_index(index_ttl: &index_path::IndexPath) -> Result<Vec<IndexEntry>, MyError> {
30
11
    let rdf = std::fs::read_to_string(index_ttl)
31
11
        .map_err(|e| MyError::io_error(index_ttl.to_path_buf(), e))?;
32
11
    let base: Iri<String> = Iri::new("http://example.com/".to_string())?;
33
11
    let parser = TurtleParser { base: Some(base) };
34
11
    let mut source = parser.parse_str(&rdf);
35
11
    let mut entries = Vec::new();
36
11
    let ldp = Namespace::new("http://www.w3.org/ns/ldp#")?;
37
11
    let ldp_contains = ldp.get("contains")?;
38
11
    source
39
35
        .for_each_triple(|t| {
40
35
            let p = t.p();
41
35
            if ldp_contains.eq(&p) {
42
24
                entries.push(IndexEntry {
43
24
                    name: t.s().to_string(),
44
24
                    base_uri: None,
45
24
                });
46
24
            }
47
35
        })
48
11
        .map_err(MyError::format_error)?;
49
11
    Ok(entries)
50
11
}
51

            
52
/**
53
 * Write index.ttl with all the given entries.
54
 * The ttl file will contain a an ldp#Container.
55
 * The entries are linked to the ldp#Container via ldp#contains predicates.
56
 */
57
11
pub fn write_index(path: &Path, entries: &[IndexEntry]) -> Result<(), Box<dyn Error>> {
58
11
    let index_path = IndexPath::try_from(path)?;
59
11
    let mut graph = LightGraph::new();
60
11
    let local = Namespace::new("")?;
61
11
    let ldp = Namespace::new("http://www.w3.org/ns/ldp#")?;
62
11
    let ldp_container = ldp.get("Container")?;
63
11
    let ldpc = local.get("")?;
64
11
    let ldp_contains = ldp.get("contains")?;
65
11
    graph.insert(ldpc, type_, ldp_container)?;
66
35
    for entry in entries {
67
24
        graph.insert(ldpc, ldp_contains, local.get(&entry.name)?)?;
68
    }
69
11
    let mut stringifier = TurtleSerializer::new_stringifier();
70
11
    let rdf = stringifier.serialize_graph(&graph)?.as_str();
71
11
    std::fs::write(index_path.as_ref(), rdf)?;
72
11
    println!("wrote {}", index_path.as_ref().display());
73
11
    Ok(())
74
11
}
75

            
76
/**
77
 * List all the files that are adjacent to an index.ttl in a directory.
78
 */
79
40
pub fn read_entries(path: &Path) -> Result<Vec<IndexEntry>, Box<dyn Error>> {
80
40
    let index_path = IndexPath::try_from(path)?;
81
10
    let mut names = Vec::new();
82
20
    for name in index_path.files()? {
83
20
        names.push(IndexEntry {
84
20
            name,
85
20
            base_uri: None,
86
20
        });
87
20
    }
88
10
    Ok(names)
89
40
}
90

            
91
10
pub fn check_index(path: &Path) -> Result<(), Box<dyn Error>> {
92
10
    let index_path = IndexPath::try_from(path)?;
93
10
    read_index(&index_path)?;
94
10
    Ok(())
95
10
}