use oxigraph::io::{RdfFormat, RdfSerializer};
use oxigraph::model::vocab::rdf;
use oxigraph::model::{BlankNode, NamedNodeRef, TripleRef};
use oxigraph::sparql::results::QueryResultsFormat;
#[cfg(feature = "geosparql")]
use spargeo::GEOSPARQL_EXTENSION_FUNCTIONS;
mod sd {
use oxigraph::model::NamedNodeRef;
pub const SERVICE: NamedNodeRef<'_> =
NamedNodeRef::new_unchecked("http://www.w3.org/ns/sparql-service-description#Service");
pub const DEFAULT_ENTAILMENT_REGIME: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
"http://www.w3.org/ns/sparql-service-description#defaultEntailmentRegime",
);
pub const ENDPOINT: NamedNodeRef<'_> =
NamedNodeRef::new_unchecked("http://www.w3.org/ns/sparql-service-description#endpoint");
#[cfg(feature = "geosparql")]
pub const EXTENSION_FUNCTION: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
"http://www.w3.org/ns/sparql-service-description#extensionFunction",
);
pub const FEATURE: NamedNodeRef<'_> =
NamedNodeRef::new_unchecked("http://www.w3.org/ns/sparql-service-description#feature");
pub const RESULT_FORMAT: NamedNodeRef<'_> =
NamedNodeRef::new_unchecked("http://www.w3.org/ns/sparql-service-description#resultFormat");
pub const SUPPORTED_LANGUAGE: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
"http://www.w3.org/ns/sparql-service-description#supportedLanguage",
);
pub const EMPTY_GRAPHS: NamedNodeRef<'_> =
NamedNodeRef::new_unchecked("http://www.w3.org/ns/sparql-service-description#EmptyGraphs");
#[cfg(any(
feature = "native-tls",
feature = "rustls-native",
feature = "rustls-webpki"
))]
pub const BASIC_FEDERATED_QUERY: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
"http://www.w3.org/ns/sparql-service-description#BasicFederatedQuery",
);
pub const SPARQL_10_QUERY: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
"http://www.w3.org/ns/sparql-service-description#SPARQL10Query",
);
pub const SPARQL_11_QUERY: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
"http://www.w3.org/ns/sparql-service-description#SPARQL11Query",
);
pub const SPARQL_11_UPDATE: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
"http://www.w3.org/ns/sparql-service-description#SPARQL11Update",
);
pub const UNION_DEFAULT_GRAPH: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
"http://www.w3.org/ns/sparql-service-description#UnionDefaultGraph",
);
}
#[derive(Eq, PartialEq, Clone, Copy)]
pub enum EndpointKind {
Query,
Update,
}
pub fn generate_service_description(
format: RdfFormat,
kind: EndpointKind,
union_default_graph: bool,
endpoint_base_url: &str,
) -> Vec<u8> {
let mut graph = Vec::new();
let root = BlankNode::default();
graph.push(TripleRef::new(&root, rdf::TYPE, sd::SERVICE));
graph.push(TripleRef::new(
&root,
sd::ENDPOINT,
NamedNodeRef::new_unchecked(match format {
RdfFormat::Turtle
| RdfFormat::TriG
| RdfFormat::N3
| RdfFormat::JsonLd { .. }
| RdfFormat::RdfXml => {
""
}
RdfFormat::NTriples | RdfFormat::NQuads | _ => {
endpoint_base_url
}
}),
));
for language in match kind {
EndpointKind::Query => [sd::SPARQL_10_QUERY, sd::SPARQL_11_QUERY].as_slice(),
EndpointKind::Update => [sd::SPARQL_11_UPDATE].as_slice(),
} {
graph.push(TripleRef::new(&root, sd::SUPPORTED_LANGUAGE, *language));
}
if kind == EndpointKind::Query {
for format in [
QueryResultsFormat::Json,
QueryResultsFormat::Xml,
QueryResultsFormat::Csv,
QueryResultsFormat::Tsv,
] {
graph.push(TripleRef::new(
&root,
sd::RESULT_FORMAT,
NamedNodeRef::new_unchecked(format.iri()),
));
}
for format in [
RdfFormat::NTriples,
RdfFormat::NQuads,
RdfFormat::Turtle,
RdfFormat::TriG,
RdfFormat::N3,
RdfFormat::RdfXml,
] {
graph.push(TripleRef::new(
&root,
sd::RESULT_FORMAT,
NamedNodeRef::new_unchecked(format.iri()),
));
}
}
#[cfg(any(
feature = "native-tls",
feature = "rustls-native",
feature = "rustls-webpki"
))]
if kind == EndpointKind::Query {
graph.push(TripleRef::new(
&root,
sd::FEATURE,
sd::BASIC_FEDERATED_QUERY,
));
}
graph.push(TripleRef::new(&root, sd::FEATURE, sd::EMPTY_GRAPHS));
if union_default_graph {
graph.push(TripleRef::new(&root, sd::FEATURE, sd::UNION_DEFAULT_GRAPH));
}
graph.push(TripleRef::new(
&root,
sd::DEFAULT_ENTAILMENT_REGIME,
NamedNodeRef::new_unchecked("http://www.w3.org/ns/entailment/Simple"),
));
#[cfg(feature = "geosparql")]
for (function_name, _) in GEOSPARQL_EXTENSION_FUNCTIONS {
graph.push(TripleRef::new(&root, sd::EXTENSION_FUNCTION, function_name));
}
let mut serializer = RdfSerializer::from_format(format)
.with_prefix("sd", "http://www.w3.org/ns/sparql-service-description#")
.unwrap()
.for_writer(Vec::new());
for t in graph {
serializer.serialize_triple(t).unwrap();
}
serializer.finish().unwrap()
}