From 81cfcff5d7d967c83f17695a94b7676f37dae03e Mon Sep 17 00:00:00 2001 From: Marcel Otto Date: Fri, 17 Aug 2018 01:31:08 +0200 Subject: [PATCH] Add default_base_iri configuration and use it for serialization readers --- CHANGELOG.md | 4 +++- README.md | 8 ++++++++ lib/rdf/iri.ex | 13 +++++++++++++ lib/rdf/serialization/reader.ex | 19 +++++++++++++++---- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1b35d9..9cef6bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,9 @@ This project adheres to [Semantic Versioning](http://semver.org/) and - the logical operators and the Effective Boolean Value (EBV) coercion algorithm from the XPath and SPARQL specs on `RDF.Boolean` - `RDF.Term.equal?/2` and `RDF.Term.equal_value?/2` -- `RDF.LangString.match_language?/2` +- `RDF.LangString.match_language?/2` +- possibility to configure an application-specific default base IRI; for now it + is used only on reading of RDF serializations (when no `base` specified) ### Changed diff --git a/README.md b/README.md index b116c2d..586651c 100644 --- a/README.md +++ b/README.md @@ -716,6 +716,14 @@ RDF.read_file!("/path/to/some_file.ttl") |> RDF.write_file!("/path/to/some_file.jsonld") ``` +For serialization formats which support it, you can provide a base IRI on the read functions with the `base` option. You can also provide a default base IRI in your application configuration, which will be used when no `base` option is given. + +```elixir +config :rdf, + default_base_iri: "http://my_app.example/" +``` + + ## Getting help diff --git a/lib/rdf/iri.ex b/lib/rdf/iri.ex index 60a7b9c..0c37a00 100644 --- a/lib/rdf/iri.ex +++ b/lib/rdf/iri.ex @@ -25,6 +25,19 @@ defmodule RDF.IRI do # see https://tools.ietf.org/html/rfc3986#appendix-B @scheme_regex Regex.recompile!(~r/^([a-z][a-z0-9\+\-\.]*):/i) + @doc """ + The default base IRI to be used when reading a serialization and no `base` 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/" + + See [section 5.1.4 of RFC 3987](https://tools.ietf.org/html/rfc3986#page-29) + """ + @default_base Application.get_env(:rdf, :default_base_iri) + def default_base, do: @default_base + @doc """ Creates a `RDF.IRI`. diff --git a/lib/rdf/serialization/reader.ex b/lib/rdf/serialization/reader.ex index d07baf5..f60e77b 100644 --- a/lib/rdf/serialization/reader.ex +++ b/lib/rdf/serialization/reader.ex @@ -2,6 +2,9 @@ defmodule RDF.Serialization.Reader do @moduledoc """ General functions for reading a `RDF.Graph` or `RDF.Dataset` from a serialization file or encoded-string. + If no base IRI is provided with the `base` option on any of these functions, + the `RDF.IRI.default_base/0` is used. + You probably won't use these functions directly, but instead use the automatically generated functions with same name on a `RDF.Serialization.Format`, which implicitly use the proper `RDF.Serialization.Decoder` module. @@ -15,7 +18,7 @@ defmodule RDF.Serialization.Reader do dataset, or `{:error, reason}` if an error occurs. """ def read_string(decoder, content, opts \\ []) do - decoder.decode(content, opts) + decoder.decode(content, with_base(opts)) end @doc """ @@ -24,7 +27,7 @@ defmodule RDF.Serialization.Reader do As opposed to `read_string`, it raises an exception if an error occurs. """ def read_string!(decoder, content, opts \\ []) do - decoder.decode!(content, opts) + decoder.decode!(content, with_base(opts)) end @doc """ @@ -35,7 +38,7 @@ defmodule RDF.Serialization.Reader do """ def read_file(decoder, file, opts \\ []) do case File.read(file) do - {:ok, content} -> read_string(decoder, content, opts) + {:ok, content} -> read_string(decoder, content, with_base(opts)) {:error, reason} -> {:error, reason} end end @@ -47,7 +50,15 @@ defmodule RDF.Serialization.Reader do """ def read_file!(decoder, file, opts \\ []) do with content = File.read!(file) do - read_string!(decoder, content, opts) + read_string!(decoder, content, with_base(opts)) + end + end + + defp with_base(opts) do + cond do + Keyword.has_key?(opts, :base) -> opts + base = RDF.IRI.default_base() -> Keyword.put(opts, :base, base) + true -> opts end end