sparql_service/
service_description.rs

1//! A set whose elements can be repeated. The set tracks how many times each element appears
2//!
3
4use std::{fmt::Display, io::BufRead, path::Path};
5
6use iri_s::IriS;
7use itertools::Itertools;
8use srdf::{RDFFormat, ReaderMode, SRDFGraph};
9
10use crate::{ServiceDescriptionError, ServiceDescriptionParser};
11
12#[derive(Clone, PartialEq, Eq, Default, Debug)]
13pub struct ServiceDescription {
14    endpoint: IriS,
15    default_dataset: Dataset,
16    supported_language: Vec<SupportedLanguage>,
17    feature: Vec<Feature>,
18    result_format: Vec<ResultFormat>,
19}
20
21#[derive(Clone, PartialEq, Eq, Default, Debug)]
22pub enum SupportedLanguage {
23    SPARQL10Query,
24
25    #[default]
26    SPARQL11Query,
27
28    SPARQL11Update,
29}
30
31impl Display for SupportedLanguage {
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33        match self {
34            SupportedLanguage::SPARQL10Query => write!(f, "SPARQL10Query"),
35            SupportedLanguage::SPARQL11Query => write!(f, "SPARQL11Query"),
36            SupportedLanguage::SPARQL11Update => write!(f, "SPARQL11Update"),
37        }
38    }
39}
40
41#[derive(Clone, PartialEq, Eq, Debug)]
42pub enum ResultFormat {
43    XML,
44    Turtle,
45    TSV,
46    RdfXml,
47    JSON,
48    NTriples,
49    CSV,
50    JsonLD,
51    Other(IriS),
52}
53
54impl Display for ResultFormat {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        match self {
57            ResultFormat::XML => write!(f, "XML"),
58            ResultFormat::Turtle => write!(f, "Turtle"),
59            ResultFormat::TSV => write!(f, "TSV"),
60            ResultFormat::RdfXml => write!(f, "RDF/XML"),
61            ResultFormat::JSON => write!(f, "JSON"),
62            ResultFormat::NTriples => write!(f, "N-TRIPLES"),
63            ResultFormat::CSV => write!(f, "CSV"),
64            ResultFormat::JsonLD => write!(f, "JSON_LD"),
65            ResultFormat::Other(iri) => write!(f, "ResultFormat({iri})",),
66        }
67    }
68}
69
70/// Features defined in: https://www.w3.org/TR/sparql11-service-description/#sd-Feature
71#[derive(Clone, PartialEq, Eq, Debug)]
72pub enum Feature {
73    DereferencesURIs,
74    UnionDefaultGraph,
75    RequiresDataset,
76    EmptyGraphs,
77    BasicFederatedQuery,
78    Other(IriS),
79}
80
81impl Display for Feature {
82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83        match self {
84            Feature::DereferencesURIs => write!(f, "DereferencesURIs"),
85            Feature::UnionDefaultGraph => write!(f, "UnionDefaultGraph"),
86            Feature::RequiresDataset => write!(f, "RequiresDataset"),
87            Feature::EmptyGraphs => write!(f, "EmptyGraphs"),
88            Feature::BasicFederatedQuery => write!(f, "BasicFederatedQuery"),
89            Feature::Other(iri) => write!(f, "Feature({iri})"),
90        }
91    }
92}
93
94#[derive(Clone, PartialEq, Eq, Default, Debug)]
95pub struct Dataset {
96    term: IriS,
97    default_graph: GraphDescription,
98    named_graphs: Vec<NamedGraphDescription>,
99}
100
101impl Dataset {
102    pub fn new(iri: &IriS) -> Dataset {
103        Dataset {
104            term: iri.clone(),
105            default_graph: GraphDescription::default(),
106            named_graphs: Vec::new(),
107        }
108    }
109}
110
111impl Display for Dataset {
112    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113        writeln!(f, "Dataset: {}", self.term)
114    }
115}
116
117#[derive(Clone, PartialEq, Eq, Default, Debug)]
118pub struct GraphDescription {
119    triples: u128,
120    class_partition: Vec<ClassPartition>,
121}
122
123#[derive(Clone, PartialEq, Eq, Default, Debug)]
124pub struct NamedGraphDescription {}
125
126#[derive(Clone, PartialEq, Eq, Default, Debug)]
127pub struct ClassPartition {
128    class: IriS,
129    property_partition: PropertyPartition,
130}
131
132#[derive(Clone, PartialEq, Eq, Default, Debug)]
133pub struct PropertyPartition {
134    property: IriS,
135    class_partition: Vec<ClassPartition>,
136    datatype_partition: Option<DatatypePartition>,
137}
138
139#[derive(Clone, PartialEq, Eq, Default, Debug)]
140pub struct DatatypePartition {
141    datatype: IriS,
142}
143
144impl ServiceDescription {
145    pub fn new(endpoint: IriS) -> ServiceDescription {
146        ServiceDescription {
147            endpoint: endpoint.clone(),
148            default_dataset: Dataset::default(),
149            supported_language: Vec::new(),
150            feature: Vec::new(),
151            result_format: Vec::new(),
152        }
153    }
154
155    pub fn from_path<P: AsRef<Path>>(
156        path: P,
157        format: &RDFFormat,
158        base: Option<&str>,
159        reader_mode: &ReaderMode,
160    ) -> Result<ServiceDescription, ServiceDescriptionError> {
161        let rdf = SRDFGraph::from_path(path, format, base, reader_mode)?;
162        let mut parser = ServiceDescriptionParser::new(rdf);
163        let service = parser.parse()?;
164        Ok(service)
165    }
166
167    pub fn from_reader<R: BufRead>(
168        read: R,
169        format: &RDFFormat,
170        base: Option<&str>,
171        reader_mode: &ReaderMode,
172    ) -> Result<ServiceDescription, ServiceDescriptionError> {
173        let rdf = SRDFGraph::from_reader(read, format, base, reader_mode)?;
174        let mut parser = ServiceDescriptionParser::new(rdf);
175        let service = parser.parse()?;
176        Ok(service)
177    }
178
179    pub fn add_supported_language(&mut self, supported_language: &[SupportedLanguage]) {
180        supported_language.clone_into(&mut self.supported_language);
181    }
182
183    pub fn add_feature(&mut self, feature: &[Feature]) {
184        feature.clone_into(&mut self.feature);
185    }
186
187    pub fn add_result_format(&mut self, result_format: &[ResultFormat]) {
188        result_format.clone_into(&mut self.result_format);
189    }
190
191    pub fn add_default_dataset(&mut self, default_dataset: &Dataset) {
192        self.default_dataset = default_dataset.clone();
193    }
194}
195
196impl Display for ServiceDescription {
197    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198        writeln!(f, "Service")?;
199        writeln!(f, "  endpoint: {}", self.endpoint.as_str())?;
200        let sup_lang = self
201            .supported_language
202            .iter()
203            .map(|l| l.to_string())
204            .join(", ");
205        writeln!(f, "  supportedLanguage: [{sup_lang}]")?;
206        let feature = self.feature.iter().map(|l| l.to_string()).join(", ");
207        writeln!(f, "  feature: [{feature}]")?;
208        let result = self.result_format.iter().map(|l| l.to_string()).join(", ");
209        writeln!(f, "  result_format: [{result}]")?;
210        writeln!(f, "  default_dataset: {}", self.default_dataset)?;
211        Ok(())
212    }
213}