871deaedeb
This isn't used currently in the library. It also invites misusage as it obfuscates the actually intended usage of RDF.Resource.Generators.
343 lines
11 KiB
Elixir
343 lines
11 KiB
Elixir
defmodule RDF do
|
|
@moduledoc """
|
|
The top-level module of RDF.ex.
|
|
|
|
RDF.ex consists of:
|
|
|
|
- modules for the nodes of an RDF graph
|
|
- `RDF.Term`
|
|
- `RDF.IRI`
|
|
- `RDF.BlankNode`
|
|
- `RDF.Literal`
|
|
- the `RDF.Literal.Datatype` system
|
|
- a facility for the mapping of URIs of a vocabulary to Elixir modules and
|
|
functions: `RDF.Vocabulary.Namespace`
|
|
- a facility for the automatic generation of resource identifiers: `RDF.Resource.Generator`
|
|
- modules for the construction of statements
|
|
- `RDF.Triple`
|
|
- `RDF.Quad`
|
|
- `RDF.Statement`
|
|
- modules for collections of statements
|
|
- `RDF.Description`
|
|
- `RDF.Graph`
|
|
- `RDF.Dataset`
|
|
- `RDF.Data`
|
|
- `RDF.List`
|
|
- `RDF.Diff`
|
|
- functions to construct and execute basic graph pattern queries: `RDF.Query`
|
|
- functions for working with RDF serializations: `RDF.Serialization`
|
|
- behaviours for the definition of RDF serialization formats
|
|
- `RDF.Serialization.Format`
|
|
- `RDF.Serialization.Decoder`
|
|
- `RDF.Serialization.Encoder`
|
|
- and the implementation of various RDF serialization formats
|
|
- `RDF.NTriples`
|
|
- `RDF.NQuads`
|
|
- `RDF.Turtle`
|
|
|
|
This top-level module provides shortcut functions for the construction of the
|
|
basic elements and structures of RDF and some general helper functions.
|
|
|
|
For a general introduction you may refer to the guides on the [homepage](https://rdf-elixir.dev).
|
|
"""
|
|
|
|
alias RDF.{
|
|
IRI,
|
|
BlankNode,
|
|
Literal,
|
|
Namespace,
|
|
Description,
|
|
Graph,
|
|
Dataset,
|
|
Serialization,
|
|
PrefixMap
|
|
}
|
|
|
|
import RDF.Guards
|
|
import RDF.Utils.Bootstrapping
|
|
|
|
@star? Application.get_env(:rdf, :star, true)
|
|
@doc """
|
|
Returns whether RDF-star support is enabled.
|
|
"""
|
|
def star?(), do: @star?
|
|
|
|
defdelegate default_base_iri(), to: IRI, as: :default_base
|
|
|
|
@standard_prefixes PrefixMap.new(
|
|
xsd: xsd_iri_base(),
|
|
rdf: rdf_iri_base(),
|
|
rdfs: rdfs_iri_base()
|
|
)
|
|
|
|
@doc """
|
|
A fixed set prefixes that will always be part of the `default_prefixes/0`.
|
|
|
|
```elixir
|
|
#{inspect(@standard_prefixes, pretty: true)}
|
|
```
|
|
|
|
See `default_prefixes/0`, if you don't want these standard prefixes to be part
|
|
of the default prefixes.
|
|
"""
|
|
def standard_prefixes(), do: @standard_prefixes
|
|
|
|
@doc """
|
|
A user-defined `RDF.PrefixMap` of prefixes to IRI namespaces.
|
|
|
|
This prefix map will be used implicitly wherever a prefix map is expected, but
|
|
not provided. For example, when you don't pass a prefix map to the Turtle serializer,
|
|
this prefix map will be used.
|
|
|
|
By default the `standard_prefixes/0` are part of this prefix map, but you can
|
|
define additional default prefixes via the `default_prefixes` compile-time
|
|
configuration.
|
|
|
|
For example:
|
|
|
|
config :rdf,
|
|
default_prefixes: %{
|
|
ex: "http://example.com/"
|
|
}
|
|
|
|
You can also set `:default_prefixes` to a module-function tuple `{mod, fun}`
|
|
with a function which should be called to determine the default prefixes.
|
|
|
|
If you don't want the `standard_prefixes/0` to be part of the default prefixes,
|
|
or you want to map the standard prefixes to different namespaces (strongly discouraged!),
|
|
you can set the `use_standard_prefixes` compile-time configuration flag to `false`.
|
|
|
|
config :rdf,
|
|
use_standard_prefixes: false
|
|
|
|
"""
|
|
case Application.get_env(:rdf, :default_prefixes, %{}) do
|
|
{mod, fun} ->
|
|
if Application.get_env(:rdf, :use_standard_prefixes, true) do
|
|
def default_prefixes() do
|
|
PrefixMap.merge!(@standard_prefixes, apply(unquote(mod), unquote(fun), []))
|
|
end
|
|
else
|
|
def default_prefixes(), do: apply(unquote(mod), unquote(fun), [])
|
|
end
|
|
|
|
default_prefixes ->
|
|
@default_prefixes PrefixMap.new(default_prefixes)
|
|
if Application.get_env(:rdf, :use_standard_prefixes, true) do
|
|
def default_prefixes() do
|
|
PrefixMap.merge!(@standard_prefixes, @default_prefixes)
|
|
end
|
|
else
|
|
def default_prefixes(), do: @default_prefixes
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Returns the `default_prefixes/0` with additional prefix mappings.
|
|
|
|
The `prefix_mappings` can be given in any format accepted by `RDF.PrefixMap.new/1`.
|
|
"""
|
|
def default_prefixes(prefix_mappings) do
|
|
default_prefixes() |> PrefixMap.merge!(prefix_mappings)
|
|
end
|
|
|
|
defdelegate read_string(string, opts), to: Serialization
|
|
defdelegate read_string!(string, opts), to: Serialization
|
|
defdelegate read_stream(stream, opts \\ []), to: Serialization
|
|
defdelegate read_stream!(stream, opts \\ []), to: Serialization
|
|
defdelegate read_file(filename, opts \\ []), to: Serialization
|
|
defdelegate read_file!(filename, opts \\ []), to: Serialization
|
|
defdelegate write_string(data, opts), to: Serialization
|
|
defdelegate write_string!(data, opts), to: Serialization
|
|
defdelegate write_stream(data, opts), to: Serialization
|
|
defdelegate write_file(data, filename, opts \\ []), to: Serialization
|
|
defdelegate write_file!(data, filename, opts \\ []), to: Serialization
|
|
|
|
@doc """
|
|
Checks if the given value is a RDF resource.
|
|
|
|
## Examples
|
|
|
|
Supposed `EX` is a `RDF.Vocabulary.Namespace` and `Foo` is not.
|
|
|
|
iex> RDF.resource?(RDF.iri("http://example.com/resource"))
|
|
true
|
|
iex> RDF.resource?(EX.resource)
|
|
true
|
|
iex> RDF.resource?(EX.Resource)
|
|
true
|
|
iex> RDF.resource?(Foo.Resource)
|
|
false
|
|
iex> RDF.resource?(RDF.bnode)
|
|
true
|
|
iex> RDF.resource?(RDF.XSD.integer(42))
|
|
false
|
|
iex> RDF.resource?(42)
|
|
false
|
|
"""
|
|
def resource?(value)
|
|
def resource?(%IRI{}), do: true
|
|
def resource?(%BlankNode{}), do: true
|
|
|
|
def resource?(qname) when maybe_ns_term(qname) do
|
|
case Namespace.resolve_term(qname) do
|
|
{:ok, iri} -> resource?(iri)
|
|
_ -> false
|
|
end
|
|
end
|
|
|
|
if @star? do
|
|
def resource?({_, _, _} = triple), do: RDF.Triple.valid?(triple)
|
|
end
|
|
|
|
def resource?(_), do: false
|
|
|
|
@doc """
|
|
Checks if the given value is a RDF term.
|
|
|
|
## Examples
|
|
|
|
Supposed `EX` is a `RDF.Vocabulary.Namespace` and `Foo` is not.
|
|
|
|
iex> RDF.term?(RDF.iri("http://example.com/resource"))
|
|
true
|
|
iex> RDF.term?(EX.resource)
|
|
true
|
|
iex> RDF.term?(EX.Resource)
|
|
true
|
|
iex> RDF.term?(Foo.Resource)
|
|
false
|
|
iex> RDF.term?(RDF.bnode)
|
|
true
|
|
iex> RDF.term?(RDF.XSD.integer(42))
|
|
true
|
|
iex> RDF.term?(42)
|
|
false
|
|
"""
|
|
def term?(value)
|
|
def term?(%Literal{}), do: true
|
|
def term?(value), do: resource?(value)
|
|
|
|
defdelegate uri?(value), to: IRI, as: :valid?
|
|
defdelegate iri?(value), to: IRI, as: :valid?
|
|
defdelegate uri(value), to: IRI, as: :new
|
|
defdelegate iri(value), to: IRI, as: :new
|
|
defdelegate uri!(value), to: IRI, as: :new!
|
|
defdelegate iri!(value), to: IRI, as: :new!
|
|
|
|
@doc """
|
|
Checks if the given value is a blank node.
|
|
|
|
## Examples
|
|
|
|
iex> RDF.bnode?(RDF.bnode)
|
|
true
|
|
iex> RDF.bnode?(RDF.iri("http://example.com/resource"))
|
|
false
|
|
iex> RDF.bnode?(42)
|
|
false
|
|
"""
|
|
def bnode?(%BlankNode{}), do: true
|
|
def bnode?(_), do: false
|
|
|
|
defdelegate bnode(), to: BlankNode, as: :new
|
|
defdelegate bnode(id), to: BlankNode, as: :new
|
|
|
|
@doc """
|
|
Checks if the given value is a RDF literal.
|
|
"""
|
|
def literal?(%Literal{}), do: true
|
|
def literal?(_), do: false
|
|
|
|
defdelegate literal(value), to: Literal, as: :new
|
|
defdelegate literal(value, opts), to: Literal, as: :new
|
|
|
|
if @star? do
|
|
alias RDF.Star.{Triple, Quad, Statement}
|
|
|
|
defdelegate triple(s, p, o, property_map \\ nil), to: Triple, as: :new
|
|
defdelegate triple(tuple, property_map \\ nil), to: Triple, as: :new
|
|
|
|
defdelegate quad(s, p, o, g, property_map \\ nil), to: Quad, as: :new
|
|
defdelegate quad(tuple, property_map \\ nil), to: Quad, as: :new
|
|
|
|
defdelegate statement(s, p, o), to: Statement, as: :new
|
|
defdelegate statement(s, p, o, g), to: Statement, as: :new
|
|
defdelegate statement(tuple, property_map \\ nil), to: Statement, as: :new
|
|
|
|
defdelegate coerce_subject(subject, property_map \\ nil), to: Statement
|
|
defdelegate coerce_predicate(predicate), to: Statement
|
|
defdelegate coerce_predicate(predicate, property_map), to: Statement
|
|
defdelegate coerce_object(object, property_map \\ nil), to: Statement
|
|
defdelegate coerce_graph_name(graph_name), to: Statement
|
|
else
|
|
alias RDF.{Triple, Quad, Statement}
|
|
|
|
defdelegate triple(s, p, o, property_map \\ nil), to: Triple, as: :new
|
|
defdelegate triple(tuple, property_map \\ nil), to: Triple, as: :new
|
|
|
|
defdelegate quad(s, p, o, g, property_map \\ nil), to: Quad, as: :new
|
|
defdelegate quad(tuple, property_map \\ nil), to: Quad, as: :new
|
|
|
|
defdelegate statement(s, p, o), to: Statement, as: :new
|
|
defdelegate statement(s, p, o, g), to: Statement, as: :new
|
|
defdelegate statement(tuple, property_map \\ nil), to: Statement, as: :new
|
|
|
|
defdelegate coerce_subject(subject), to: Statement
|
|
defdelegate coerce_predicate(predicate), to: Statement
|
|
defdelegate coerce_predicate(predicate, property_map), to: Statement
|
|
defdelegate coerce_object(object), to: Statement
|
|
defdelegate coerce_graph_name(graph_name), to: Statement
|
|
end
|
|
|
|
defdelegate description(subject, opts \\ []), to: Description, as: :new
|
|
|
|
defdelegate graph(), to: Graph, as: :new
|
|
defdelegate graph(arg), to: Graph, as: :new
|
|
defdelegate graph(arg1, arg2), to: Graph, as: :new
|
|
|
|
defdelegate dataset(), to: Dataset, as: :new
|
|
defdelegate dataset(arg), to: Dataset, as: :new
|
|
defdelegate dataset(arg1, arg2), to: Dataset, as: :new
|
|
|
|
defdelegate diff(arg1, arg2), to: RDF.Diff
|
|
|
|
defdelegate list?(resource, graph), to: RDF.List, as: :node?
|
|
defdelegate list?(description), to: RDF.List, as: :node?
|
|
|
|
def list(native_list), do: RDF.List.from(native_list)
|
|
def list(head, %Graph{} = graph), do: RDF.List.new(head, graph)
|
|
def list(native_list, opts), do: RDF.List.from(native_list, opts)
|
|
|
|
defdelegate prefix_map(prefixes), to: RDF.PrefixMap, as: :new
|
|
defdelegate property_map(property_map), to: RDF.PropertyMap, as: :new
|
|
|
|
############################################################################
|
|
# These alias functions for the RDF.NS.RDF namespace are mandatory.
|
|
# Without them the property functions are inaccessible, since the namespace
|
|
# can't be aliased, because it gets in conflict with the root namespace
|
|
# of the project.
|
|
|
|
defdelegate langString(value, opts), to: RDF.LangString, as: :new
|
|
defdelegate lang_string(value, opts), to: RDF.LangString, as: :new
|
|
|
|
for term <- ~w[type subject predicate object first rest value]a do
|
|
defdelegate unquote(term)(), to: RDF.NS.RDF
|
|
@doc false
|
|
defdelegate unquote(term)(s, o), to: RDF.NS.RDF
|
|
@doc false
|
|
defdelegate unquote(term)(s, o1, o2), to: RDF.NS.RDF
|
|
@doc false
|
|
defdelegate unquote(term)(s, o1, o2, o3), to: RDF.NS.RDF
|
|
@doc false
|
|
defdelegate unquote(term)(s, o1, o2, o3, o4), to: RDF.NS.RDF
|
|
@doc false
|
|
defdelegate unquote(term)(s, o1, o2, o3, o4, o5), to: RDF.NS.RDF
|
|
end
|
|
|
|
defdelegate langString(), to: RDF.NS.RDF
|
|
defdelegate lang_string(), to: RDF.NS.RDF, as: :langString
|
|
defdelegate unquote(nil)(), to: RDF.NS.RDF
|
|
|
|
defdelegate __base_iri__(), to: RDF.NS.RDF
|
|
end
|