Skip to content

Commit

Permalink
improve doc and mdbook
Browse files Browse the repository at this point in the history
  • Loading branch information
pchampin committed Dec 18, 2023
1 parent 5628f60 commit 12b9300
Show file tree
Hide file tree
Showing 17 changed files with 362 additions and 35 deletions.
9 changes: 4 additions & 5 deletions api/src/dataset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,14 @@ pub trait Dataset {
/// [`SimpleTerm`]: crate::term::SimpleTerm
/// [`Any`]: crate::term::matcher::Any
/// ```
/// # use sophia_api::dataset::Dataset;
/// # use sophia_api::quad::Quad;
/// # use sophia_api::prelude::*;
/// # use sophia_api::ns::{Namespace, rdf};
/// #
/// # fn test<G: Dataset>(dataset: &G) -> Result<(), Box<dyn std::error::Error>>
/// # where
/// # G: Dataset,
/// # {
/// #
/// use sophia_api::term::matcher::Any;
///
/// let s = Namespace::new("http://schema.org/")?;
/// let city = s.get("City")?;
/// let country = s.get("Country")?;
Expand Down Expand Up @@ -357,6 +354,8 @@ pub trait MutableDataset: Dataset {
/// a return value of `false` means that the dataset was not changed,
/// because the quad was already present in this [`SetDataset`].
///
/// See also [`MutableDataset::insert_quad`]
///
/// # Usage
/// ```
/// # use sophia_api::dataset::{MutableDataset, MdResult};
Expand Down Expand Up @@ -393,7 +392,7 @@ pub trait MutableDataset: Dataset {
/// NB: if you want to insert a quad `q` while keeping its ownership,
/// you can still pass [`q.spog()`](Quad::spog).
///
/// See also [MutableDataset::insert]
/// See also [`MutableDataset::insert`]
fn insert_quad<T>(&mut self, quad: T) -> MdResult<Self, bool>
where
T: Quad,
Expand Down
16 changes: 6 additions & 10 deletions api/src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,17 +103,14 @@ pub trait Graph {
/// [`SimpleTerm`]: crate::term::SimpleTerm
/// [`Any`]: crate::term::matcher::Any
/// ```
/// # use sophia_api::graph::Graph;
/// # use sophia_api::triple::Triple;
/// # use sophia_api::prelude::*;
/// # use sophia_api::ns::{Namespace, rdf};
/// #
/// # fn test<G: Graph>(graph: &G) -> Result<(), Box<dyn std::error::Error>>
/// # where
/// # G: Graph,
/// # {
/// #
/// use sophia_api::term::matcher::Any;
///
/// let s = Namespace::new("http://schema.org/")?;
/// let city = s.get("City")?;
/// let country = s.get("Country")?;
Expand All @@ -128,18 +125,15 @@ pub trait Graph {
/// Here is another example using a closure as a [`TermMatcher`].
///
/// ```
/// # use sophia_api::graph::Graph;
/// # use sophia_api::term::{SimpleTerm, Term};
/// # use sophia_api::triple::Triple;
/// # use sophia_api::prelude::*;
/// # use sophia_api::ns::rdfs;
/// # use sophia_api::term::SimpleTerm;
/// #
/// # fn test<G>(graph: &G) -> Result<(), Box<dyn std::error::Error>>
/// # where
/// # G: Graph,
/// # {
/// #
/// use sophia_api::term::matcher::Any;
///
/// for t in graph.triples_matching(
/// Any,
/// [&rdfs::label],
Expand Down Expand Up @@ -323,6 +317,8 @@ pub trait MutableGraph: Graph {
/// a return value of `false` means that the graph was not changed,
/// because the triple was already present in this [`SetGraph`].
///
/// See also [`insert_triple`](MutableGraph::insert_triple)
///
/// # Usage
/// ```
/// # use sophia_api::graph::{MutableGraph, MgResult};
Expand Down Expand Up @@ -350,7 +346,7 @@ pub trait MutableGraph: Graph {
/// NB: if you want to insert a triple `t` while keeping its ownership,
/// you can still pass [`t.spo()`](Triple::spo).
///
/// See also [MutableGraph::insert]
/// See also [`MutableGraph::insert`]
fn insert_triple<T>(&mut self, triple: T) -> MgResult<Self, bool>
where
T: Triple,
Expand Down
2 changes: 1 addition & 1 deletion api/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub use crate::quad::Quad;
pub use crate::serializer::{QuadSerializer, Stringifier, TripleSerializer};
pub use crate::source::{QuadSource, StreamResultExt, TripleSource};
pub use crate::sparql::{SparqlBindings, SparqlDataset};
pub use crate::term::Term;
pub use crate::term::{matcher::Any, Term, TermKind};
pub use crate::triple::Triple;

pub use sophia_iri::{Iri, IriRef};
4 changes: 2 additions & 2 deletions api/src/quad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,15 @@ pub trait Quad: Sized {

/// Check whether `other` is term-wise equal (using [`Term::eq`]) to `self`.
///
/// See also [`eq_spog`](Quad::eq_spog).
/// See also [`eq_spog`](Quad::eq_spog), [`matched_by`](Quad::matched_by).
#[inline]
fn eq<T: Quad>(&self, other: T) -> bool {
self.eq_spog(other.s(), other.p(), other.o(), other.g())
}

/// Check whether the quad (`s`, `p`, `o`) is term-wise equal (using [`Term::eq`]) to `self`.
///
/// See also [`eq`](Quad::eq).
/// See also [`eq`](Quad::eq), [`matched_by`](Quad::matched_by).
fn eq_spog<S: Term, P: Term, O: Term, G: Term>(
&self,
s: S,
Expand Down
4 changes: 2 additions & 2 deletions api/src/triple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,15 @@ pub trait Triple: Sized {

/// Check whether `other` is term-wise equal (using [`Term::eq`]) to `self`.
///
/// See also [`eq_spo`](Triple::eq_spo).
/// See also [`eq_spo`](Triple::eq_spo), [`matched_by`](Triple::matched_by).
#[inline]
fn eq<T: Triple>(&self, other: T) -> bool {
self.eq_spo(other.s(), other.p(), other.o())
}

/// Check whether the triple (`s`, `p`, `o`) is term-wise equal (using [`Term::eq`]) to `self`.
///
/// See also [`eq`](Triple::eq).
/// See also [`eq`](Triple::eq), [`matched_by`](Triple::matched_by).
fn eq_spo<S: Term, P: Term, O: Term>(&self, s: S, p: P, o: O) -> bool {
self.s().eq(s) && self.p().eq(p) && self.o().eq(o)
}
Expand Down
5 changes: 5 additions & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@
- [Introduction](./ch00_introduction.md)
- [Getting Started](./ch01_getting_started.md)
- [RDF Terms](./ch02_rdf_terms.md)
- [RDF Statements](./ch03_rdf_statements.md)
- [RDF Graphs](./ch04_rdf_graphs.md)
- [Term Matchers](./ch05_term_matchers.md)
- [RDF Datasets](./ch06_rdf_datasets.md)
- [Parsing and Serializing](./ch07_parsing_and_serializing.md)
- [Changes since version 0.7](./ch90_changes_since_07.md)
2 changes: 1 addition & 1 deletion book/src/ch00_introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The [sophia crate](https://crates.io/crates/sophia) aims at providing a comprehe

In Sophia, each of these core concepts is modeled by a trait, which can be implemented in multiple ways (see for example the [`Graph`] trait and [some of the types implementing it](https://docs.rs/sophia_api/latest/sophia_api/graph/trait.Graph.html#foreign-impls)). Sophia is therefore not meant to provide the "ultimate" implementation of RDF in Rust, but a generic framework to help various implementations to interoperate with each other (in the spirit of [Apache Commons RDF] for Java or [RDFJS] for Javascript/Typescript).

## Generalized vs. Strict RDF model
## Generalized vs. Strict RDF model {#generialized}
The data model supported by this Sophia is in fact
a superset of the RDF data model as defined by the W3C.
When the distinction matters,
Expand Down
39 changes: 29 additions & 10 deletions book/src/ch02_rdf_terms.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# RDF Terms

The [`Term`] trait defines how you interad with [RDF terms] in Sophia.
The [`Term`] trait defines how you interact with [RDF terms] in Sophia.

## Using terms

Expand All @@ -9,9 +9,9 @@ The kind is described by the [`TermKind`] enum,
and available from the [`Term::kind`] method.

```rust,noplayground
# use sophia::api::term::{FromTerm, SimpleTerm, Term, TermKind};
# use sophia::api::term::{SimpleTerm, Term, TermKind};
# use TermKind::*;
# let some_term = SimpleTerm::from_term("foo");
# let some_term: SimpleTerm = "foo".into_term();
match some_term.kind() {
Iri => { /* ... */ }
Literal => { /* ... */ }
Expand All @@ -24,12 +24,12 @@ Alternatively, when only one kind is of interest, you can use [`Term::is_iri`],

If you are interested in the "value" of the term, the trait provides the following methods. All of them return an `Option`, which will be `None` if the term does not have the corresponding kind.

* If the term is an IRI, [`Term::iri`] returns that IRI.
* If the term is an IRI, [`Term::iri`] returns that IRI[^relative_iris].
* If the term is a blank node, [`Term::bnode_id`] returns its [blank node identifier].
* If the term is a literal:

+ [`Term::lexical_form`] returns its [lexical form] (the "textual value" of the literal),
+ [`Term::datatype`] returns its datatype IRI,
+ [`Term::datatype`] returns its datatype IRI[^relative_iris],
+ [`Term::language_tag`] returns its [language tag], if any.

* If the term is a [quoted triple]:
Expand All @@ -39,7 +39,7 @@ If you are interested in the "value" of the term, the trait provides the followi
+ [`Term::atoms`] iterates over all its atomic (i.e. non quoted-triple) constituents.
+ (those three methods also have a `to_X` version that destructs the original term instead of borrowing it)

* If the term is a variable, [`Term::variable`] returns its name.
* If the term is a variable[^variables], [`Term::variable`] returns its name.

Finally, the method [`Term::eq`] can be used to check whether two values implementing [`Term`] represent the same RDF term. Note that the `==` operator may give a different result than [`Term::eq`] on some types implementing the [`Term`] trait.

Expand All @@ -49,15 +49,17 @@ Finally, the method [`Term::eq`] can be used to check whether two values impleme
Below is a list of useful types implementing the [`Term`] trait:

* [`Iri`]`<T>` and [`IriRef`]`<T>`, where `T: Borrow<str>`, representing IRIs
* [`BnodeId`]`<T>, where `T: Borrow<str>`, representing blank nodes
* [`BnodeId`]`<T>`, where `T: Borrow<str>`, representing blank nodes
* `str`, representing literals of type `xsd:string`,
* `i32`, `isize` and `usize` representing literals of type `xsd:integer`,
* `f64` representing literals of type `xsd:double`,
* [`SimpleTerm`](see below).

[`SimpleTerm`] is a straightforward implementation of [`Term`], that can represent any kind of term, and can either own its own underlying data or borrow it from something else.

Any term can be converted to a [`SimpleTerm`] using the [`Term::as_simple`] method. This method borrows as much as possible from the initial term. Alternatively, to convert any term to a self-sufficient [`SimpleTerm`], you can use [`Term::into_term`]
Any term can be converted to a [`SimpleTerm`] using the [`Term::as_simple`] method.
This method borrows as much as possible from the initial term to avoid spurious memory allocation.
Alternatively, to convert any term to a self-sufficient [`SimpleTerm`], you can use [`Term::into_term`]

See also the list of [recipes](#recipes-for-constructing-terms) below.

Expand Down Expand Up @@ -129,10 +131,27 @@ let b = BnodeId::new("x");
# Ok(()) }
```

### Converting terms into a different type
```rust,noplayground
# use sophia::api::{ns::xsd, term::{SimpleTerm, Term}};
fn main() -> Result<(), Box<dyn std::error::Error>> {
# let some_term = "42" * xsd::integer;
let t1: SimpleTerm = "hello".into_term();
let t2: i32 = some_term.try_into_term()?;
# Ok(()) }
```

----

[^relative_iris]: Note that in Sophia's [generalized RDF] model,
IRIs can be *relative* IRI reference.

[^variables]: Note that this kind only exist in Sophia's [generalized RDF] model.


[`Term`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/term/trait.Term.html
[RDF terms]: https://www.w3.org/TR/rdf-concepts/#dfn-rdf-term
[generalized RDF]: ch00_introduction.html#generalized-vs-strict-rdf-model
[generalized RDF]: ch00_introduction.html#generalized
[`TermKind`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/term/enum.TermKind.html
[`Term::kind`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/term/trait.Term.html#tymethod.kind
[`Term::is_iri`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/term/trait.Term.html#method.is_iri
Expand Down Expand Up @@ -166,4 +185,4 @@ let b = BnodeId::new("x");
[`Iri`]: https://docs.rs/sophia_iri/0.8.0-alpha.3/sophia_iri/struct.Iri.html
[`IriRef`]: https://docs.rs/sophia_iri/0.8.0-alpha.3/sophia_iri/struct.IriRef.html
[`BnodeId`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/term/bnode_id/struct.BnodeId.html
[`SimpleTerm`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/term/enum.SimpleTerm.html
[`SimpleTerm`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/term/enum.SimpleTerm.html
92 changes: 92 additions & 0 deletions book/src/ch03_rdf_statements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# RDF Statements

The [`Triple`] and [`Quad`] traits define how you interact with [RDF statements] in Sophia.

Note that in Sophia's [generalized RDF] model, terms of any kind can occur in any position in a statement.
This contrasts to strict RDF where only IRIs can occur in predicate position,
and where literals can not occur in the subject position.


## Using triples

Triples in RDF are made of a subject, a predicate and an object.
They can be obtained respectively via the methods [`Triple::s`], [`Triple::p`] and [`Triple::o`],
or all at once (as an array of three terms) via the method [`Triple::spo`].
These methods also have a `to_X` version that destructs the original triple instead of borrowing it.

```rust,noplayground
# use sophia::api::{ns::rdf, prelude::*};
// Example: yield all the tems besing used as types in the given triples
fn all_types<IT, T>(triples: IT) -> impl Iterator<Item=T::Term>
where
IT: IntoIterator<Item=T>,
T: Triple,
{
triples
.into_iter()
.filter(|t| rdf::type_ == t.p())
.map(|t| t.to_o())
}
```

## Using quads

Quads are used to represent triples in the context of an optional [named graph].
Like triples, they have methods [`Quad::s`], [`Quad::p`] and [`Quad::o`],
but also [`Quad::g`] to access the optional graph name,
and [`Quad::spog`] to obtain all four components all at once.
These methods also have a `to_X` version that destructs the original quad instead of borrowing it.

```rust,noplayground
# use sophia::api::{ns::rdf, prelude::*};
// Example: yield all the triples in the default graph, from a list of quads
fn all_types<IQ, Q>(quads: IQ) -> impl Iterator<Item=[Q::Term; 3]>
where
IQ: IntoIterator<Item=Q>,
Q: Quad,
{
quads
.into_iter()
.filter(|q| q.g().is_none())
.map(|q| { let (spo, _g) = q.to_spog(); spo })
}
```

## Comparing triples or quads

To check whether two values implementing [`Triple`] (resp. [`Quad`])
represent the same RDF statements, the method [`Triple::eq`] (resp. [`Quad::eq`])
must be used.r
It will compare each component of the statements using the [`Term::eq`] method.
Note that the `==` operator may give a different result than [`Triple::eq`] or [`Quad::eq`]
on some types implementing the [`Triple`] or the [`Quad`] trait.


## Useful types implementing [`Triple`]

While the [`Triple`] and [`Quad`] traits can be implemented by multiple types,
in most situations the following types will be used:

* `[T; 3]` where `T: `[`Term`] implements [`Triple`]
* `([T; 3], Option<T>)` where `T: `[`Term`] implements [`Quad`]



[RDF statements]: https://www.w3.org/TR/rdf-concepts/#dfn-rdf-statement
[generalized RDF]: ch00_introduction.html#generalized
[`Triple`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/triple/trait.Triple.html
[`Quad`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/quad/trait.Quad.html
[`Triple::s`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/triple/trait.Triple.html#tymethod.s
[`Triple::p`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/triple/trait.Triple.html#tymethod.p
[`Triple::o`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/triple/trait.Triple.html#tymethod.o
[`Triple::spo`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/triple/trait.Triple.html#method.spo
[named graph]: https://www.w3.org/TR/rdf-concepts/#dfn-named-graph
[`Quad::s`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/quad/trait.Quad.html#tymethod.s
[`Quad::p`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/quad/trait.Quad.html#tymethod.p
[`Quad::o`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/quad/trait.Quad.html#tymethod.o
[`Quad::g`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/quad/trait.Quad.html#tymethod.g
[`Quad::spog`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/quad/trait.Quad.html#method.spog
[`Term::eq`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/term/trait.Term.html#method.eq
[`Triple::eq`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/triple/trait.Triple.html#method.eq
[`Quad::eq`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/quad/trait.Quad.html#method.eq
[`Term`]: https://docs.rs/sophia_api/0.8.0-alpha.3/sophia_api/term/trait.Term.html
Loading

0 comments on commit 12b9300

Please sign in to comment.