# `RDF.Quad`
[🔗](https://github.com/rdf-elixir/rdf-ex/blob/v3.0.1/lib/rdf/model/quad.ex#L1)

Helper functions for RDF quads.

An RDF Quad is represented as a plain Elixir tuple consisting of four valid
RDF values for subject, predicate, object and a graph name.

# `coercible`

```elixir
@type coercible() ::
  {RDF.Statement.coercible_subject(), RDF.Statement.coercible_predicate(),
   RDF.Statement.coercible_object(), RDF.Statement.coercible_graph_name()}
```

# `mapping_value`

```elixir
@type mapping_value() :: {String.t(), String.t(), any(), String.t()}
```

# `t`

```elixir
@type t() ::
  {RDF.Statement.subject(), RDF.Statement.predicate(), RDF.Statement.object(),
   RDF.Statement.graph_name()}
```

# `bnodes`

```elixir
@spec bnodes(t()) :: [RDF.BlankNode.t()]
```

Returns a list of all `RDF.BlankNode`s within the given `quad`.

# `has_bnode?`

```elixir
@spec has_bnode?(t()) :: boolean()
```

Returns whether the given `quad` contains a blank node.

# `include_value?`

# `include_value?`

```elixir
@spec include_value?(t(), any()) :: boolean()
```

Returns whether the given `value` is a component of the given `triple`.

# `map`

```elixir
@spec map(t(), RDF.Statement.term_mapping()) :: mapping_value() | nil
```

Returns a tuple where each element from a `RDF.Quad` is mapped with the given function.

Returns `nil` if one of the components of the given tuple is not convertible via `RDF.Term.value/1`.

The function `fun` will receive a tuple `{statement_position, rdf_term}` where
`statement_position` is one of the atoms `:subject`, `:predicate`, `:object` or
`:graph_name` while `rdf_term` is the RDF term to be mapped. When the given function
returns `nil` this will be interpreted as an error and will become the overhaul
result of the `map/2` call.

## Examples

    iex> {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}
    ...> |> RDF.Quad.map(fn
    ...>      {:object, object} ->
    ...>        RDF.Term.value(object)
    ...>      {:graph_name, graph_name} ->
    ...>        graph_name
    ...>      {_, resource} ->
    ...>        resource |> to_string() |> String.last() |> String.to_atom()
    ...>    end)
    {:S, :p, 42, ~I<http://example.com/Graph>}

# `new`

```elixir
@spec new(RDF.Statement.coercible(), RDF.PropertyMap.t() | nil) :: t()
```

Creates a `RDF.Quad` with proper RDF values.

An error is raised when the given elements are not coercible to RDF values.

Note: The `RDF.quad` function is a shortcut to this function.

## Examples

    iex> RDF.Quad.new {"http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph"}
    {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}

    iex> RDF.Quad.new {EX.S, EX.p, 42, EX.Graph}
    {RDF.iri("http://example.com/S"), RDF.iri("http://example.com/p"), RDF.literal(42), RDF.iri("http://example.com/Graph")}

    iex> RDF.Quad.new {EX.S, EX.p, 42}
    {RDF.iri("http://example.com/S"), RDF.iri("http://example.com/p"), RDF.literal(42), nil}

    iex> RDF.Quad.new {EX.S, :p, 42, EX.Graph}, RDF.PropertyMap.new(p: EX.p)
    {RDF.iri("http://example.com/S"), RDF.iri("http://example.com/p"), RDF.literal(42), RDF.iri("http://example.com/Graph")}

# `new`

```elixir
@spec new(
  RDF.Statement.coercible_subject(),
  RDF.Statement.coercible_predicate(),
  RDF.Statement.coercible_object(),
  RDF.Statement.coercible_graph_name(),
  RDF.PropertyMap.t() | nil
) :: t()
```

Creates a `RDF.Quad` with proper RDF values.

An error is raised when the given elements are not coercible to RDF values.

Note: The `RDF.quad` function is a shortcut to this function.

## Examples

    iex> RDF.Quad.new("http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph")
    {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}

    iex> RDF.Quad.new(EX.S, EX.p, 42, EX.Graph)
    {RDF.iri("http://example.com/S"), RDF.iri("http://example.com/p"), RDF.literal(42), RDF.iri("http://example.com/Graph")}

    iex> RDF.Quad.new(EX.S, :p, 42, EX.Graph, RDF.PropertyMap.new(p: EX.p))
    {RDF.iri("http://example.com/S"), RDF.iri("http://example.com/p"), RDF.literal(42), RDF.iri("http://example.com/Graph")}

# `valid?`

```elixir
@spec valid?(t() | any()) :: boolean()
```

Checks if the given tuple is a valid RDF quad.

The elements of a valid RDF quad must be RDF terms. On the subject
position only IRIs and blank nodes allowed, while on the predicate and graph
name position only IRIs allowed. The object position can be any RDF term.

# `values`

```elixir
@spec values(
  t(),
  keyword()
) :: mapping_value() | nil
```

Returns a tuple of native Elixir values from a `RDF.Quad` of RDF terms.

When a `:context` option is given with a `RDF.PropertyMap`, predicates will
be mapped to the terms defined in the `RDF.PropertyMap`, if present.

Returns `nil` if one of the components of the given tuple is not convertible via `RDF.Term.value/1`.

## Examples

    iex> RDF.Quad.values {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}
    {"http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph"}

    iex> {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}
    ...> |> RDF.Quad.values(context: %{p: ~I<http://example.com/p>})
    {"http://example.com/S", :p, 42,  "http://example.com/Graph"}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
