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

A structure for IRIs.

This structure just wraps a plain IRI string and doesn't bother with the
components of the IRI, since in the context of RDF there are usually very many
IRIs and parsing them isn't needed in most cases. For these reasons we don't
use Elixirs built-in `URI` structure, because it would be unnecessary
expensive in terms of performance and memory.

The component parts can always be retrieved with the `RDF.IRI.parse/1`
function, which returns Elixirs built-in `URI` structure. Note, that `URI`
doesn't escape Unicode characters by default, so it's a suitable structure for
IRIs.

see <https://tools.ietf.org/html/rfc3987>

# `coercible`

```elixir
@type coercible() :: String.t() | URI.t() | module() | t()
```

# `t`

```elixir
@type t() :: %RDF.IRI{value: String.t()}
```

# `absolute`

```elixir
@spec absolute(coercible(), coercible()) :: t() | nil
```

Resolves a relative IRI against a base IRI.

as specified in [section 5.1 Establishing a Base URI of RFC3986](http://tools.ietf.org/html/rfc3986#section-5.1).
Only the basic algorithm in [section 5.2 of RFC3986](http://tools.ietf.org/html/rfc3986#section-5.2)
is used; neither Syntax-Based Normalization nor Scheme-Based Normalization are performed.

Characters additionally allowed in IRI references are treated in the same way that unreserved
characters are treated in URI references, per [section 6.5 of RFC3987](http://tools.ietf.org/html/rfc3987#section-6.5)

If the given `base` is not an absolute IRI `nil` is returned.

# `absolute?`

```elixir
@spec absolute?(any()) :: boolean()
```

Checks if the given value is an absolute IRI.

An absolute IRI is defined in [RFC3987](http://www.ietf.org/rfc/rfc3987.txt)
containing a scheme along with a path and optional query and fragment segments.

# `append`

```elixir
@spec append(t() | module(), String.t()) :: t()
```

Appends a String to a `RDF.IRI`.

## Example

    iex> ~I<http://example.com/> |> RDF.IRI.append("foo")
    ~I<http://example.com/foo>

    iex> EX.foo |> RDF.IRI.append("bar")
    EX.foobar

    iex> EX.Foo |> RDF.IRI.append("bar")
    RDF.iri(EX.Foobar)

# `coerce_base`

```elixir
@spec coerce_base(coercible()) :: t()
```

Coerces an IRI serving as a base IRI.

As opposed to `new/1` this also accepts bare `RDF.Vocabulary.Namespace` modules
and uses the base IRI from their definition.

# `default_base`

The default base IRI to be used when reading a serialization and no `base_iri` option is provided.

The value can be set via the `default_base_iri` configuration. For example:

    config :rdf,
      default_base_iri: "http://my_app.example/"

You can also set `:default_base_iri` to a module-function tuple `{mod, fun}`
with a function which should be called to determine the default base IRI.

See [section 5.1.4 of RFC 3987](https://tools.ietf.org/html/rfc3986#page-29)

# `ends_with?`

```elixir
@spec ends_with?(t() | module(), String.t() | [String.t()]) :: boolean()
```

Checks whether `iri` end with any of the given suffixes.

## Examples

    iex> RDF.IRI.ends_with?(~I<http://example.com/foo>, "foo")
    true
    iex> RDF.IRI.ends_with?(EX.Foo, "Foo")
    true
    iex> RDF.IRI.ends_with?(~I<http://example.com/foo>, ["foo", "bar"])
    true
    iex> RDF.IRI.ends_with?(~I<http://example.com/foo>, "bar")
    false

# `equal_value?`

```elixir
@spec equal_value?(
  t() | RDF.Literal.t() | atom(),
  t() | RDF.Literal.t() | URI.t() | atom()
) ::
  boolean() | nil
```

Tests for value equality of IRIs.

Returns `nil` when the given arguments are not comparable as IRIs.

see <https://www.w3.org/TR/rdf-concepts/#section-Graph-URIref>

# `in_namespace?`

```elixir
@spec in_namespace?(t() | module(), String.t() | t() | module()) :: boolean()
```

Checks whether `iri` lies in `namespace`.

## Examples

    iex> RDF.IRI.in_namespace?(~I<http://example.com/foo>, ~I<http://example.com/>)
    true
    iex> RDF.IRI.in_namespace?(EX.Foo, ~I<http://example.com/>)
    true
    iex> RDF.IRI.in_namespace?(~I<http://example.com/foo/bar>, "http://example.com/")
    true
    iex> RDF.IRI.in_namespace?(~I<http://example.com/#foo>, EX)
    true

# `merge`

```elixir
@spec merge(coercible(), coercible()) :: t()
```

Merges two IRIs.

This function merges two IRIs as per
[RFC 3986, section 5.2](https://tools.ietf.org/html/rfc3986#section-5.2).

# `merge!`

```elixir
@spec merge!(coercible(), coercible()) :: t()
```

Merges two IRIs and fails when the given base or the result of the merge is not a valid IRI.

This function merges two IRIs as per
[RFC 3986, section 5.2](https://tools.ietf.org/html/rfc3986#section-5.2).

# `new`

```elixir
@spec new(coercible()) :: t()
```

Creates a `RDF.IRI`.

# `new!`

```elixir
@spec new!(coercible()) :: t()
```

Creates a `RDF.IRI`, but checks if the given IRI is valid.

If the given IRI is not valid a `RDF.IRI.InvalidError` is raised.

see `valid?/1`

# `parse`

```elixir
@spec parse(coercible()) :: URI.t()
```

Parses an IRI into its components and returns them as an `URI` struct.

# `scheme`

```elixir
@spec scheme(coercible()) :: String.t() | nil
```

Returns the scheme of the given IRI

If the given string is not a valid absolute IRI, `nil` is returned.

## Examples

    iex> RDF.IRI.scheme("http://www.example.com/foo")
    "http"
    iex> RDF.IRI.scheme("not an iri")
    nil

# `starts_with?`

```elixir
@spec starts_with?(t() | module(), String.pattern()) :: boolean()
```

Checks whether `iri` starts with any of the given prefixes.

## Examples

    iex> RDF.IRI.starts_with?(~I<http://example.com/foo>, "http://example.com/")
    true
    iex> RDF.IRI.starts_with?(EX.Foo, "http://example.com/")
    true
    iex> RDF.IRI.starts_with?(~I<http://example.com/foo/bar>, ["http://example.com/", "http://example.org/"])
    true
    iex> RDF.IRI.starts_with?(~I<http://example.com/#foo>, "http://example.org/")
    false

# `to_string`

```elixir
@spec to_string(t() | module()) :: String.t()
```

Returns the given IRI as a string.

Note that this function can also handle `RDF.Vocabulary.Namespace` terms.

## Examples

    iex> RDF.IRI.to_string RDF.IRI.new("http://example.com/#foo")
    "http://example.com/#foo"
    iex> RDF.IRI.to_string EX.foo
    "http://example.com/#foo"
    iex> RDF.IRI.to_string EX.Foo
    "http://example.com/#Foo"

# `valid!`

```elixir
@spec valid!(coercible()) :: coercible()
```

Returns the given value unchanged if it's a valid IRI, otherwise raises an exception.

## Examples

    iex> RDF.IRI.valid!("http://www.example.com/foo")
    "http://www.example.com/foo"
    iex> RDF.IRI.valid!(RDF.IRI.new("http://www.example.com/foo"))
    RDF.IRI.new("http://www.example.com/foo")
    iex> RDF.IRI.valid!("not an iri")
    ** (RDF.IRI.InvalidError) Invalid IRI: "not an iri"

# `valid?`

```elixir
@spec valid?(coercible()) :: boolean()
```

Checks if the given IRI is valid according to RFC 3987.

## Examples

    iex> RDF.IRI.valid?("http://www.example.com/foo")
    true

    iex> RDF.IRI.valid?("urn:isbn:0451450523")
    true

    iex> RDF.IRI.valid?("http://example.com/path with spaces")
    false

    iex> RDF.IRI.valid?("example.com")
    false

---

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