Current section

Files

Jump to
dspace_ex lib dspace api metadata.ex
Raw

lib/dspace/api/metadata.ex

defmodule DSpace.API.Metadata do
@moduledoc """
Functions for working with metadata schemas and fields.
"""
import DSpace.Utils, only: [is_nonempty_binary: 1, pop_pagination: 1]
alias DSpace.API.Operation
alias DSpace.API.StreamBuilder
alias DSpace.API.Transform
@ep_fields "/api/core/metadatafields"
@ep_fields_search @ep_fields <> "/search/byFieldName"
@ep_fields_by_schema @ep_fields <> "/search/bySchema"
@ep_schemas "/api/core/metadataschemas"
# Public API
@doc """
Fetches a single metadata field by ID.
"""
@spec fetch_field(binary()) :: Operation.t()
def fetch_field(id) when is_nonempty_binary(id) do
%Operation.JSON{path: @ep_fields <> "/" <> id}
end
@doc """
Lists metadata fields of the repository.
Providing a schema option limits the results to the fields defined by the schema. The API
currently doesn't support providing several schemas at once.
This operation can be streamed.
## Options
* `:schema` - prefix of a metadata schema (e.g., "dc")
* `:page` - Page number (0-based, defaults to 0)
* `:size` - Number of items per page (usually defaults to 20)
"""
@spec list_fields(keyword()) :: Operation.t()
def list_fields(options \\ []) when is_list(options) do
{maybe_schema, options} = Keyword.pop(options, :schema)
{pagination, options} = pop_pagination(options)
params = pagination ++ options
transformer = &Transform.transform_collection(&1, extract: ["_embedded", "metadatafields"])
op =
if is_nonempty_binary(maybe_schema) do
%Operation.JSON{
path: @ep_fields_by_schema,
params: Keyword.merge([schema: maybe_schema], params),
transformer: transformer
}
else
%Operation.JSON{
path: @ep_fields,
params: params,
transformer: transformer
}
end
%{op | stream_impl: &StreamBuilder.new(&1, op, &2)}
end
@doc """
Finds metadata fields based on the given options.
This operation can be streamed.
## Options
* `:name` - exact fully qualified field (e.g., "dc.title", "dc.contributor.author")
* `:schema` - prefix of the metadata schema (e.g., "dc", "eperson")
* `:element` - a field's element (e.g., "contributor", "title")
* `:qualifier` - a field's qualifier (e.g., "author")
* `:query` – search term (e.g., "dc.ti", "contributor", "auth", "contributor.ot")
* `:page` - Page number (0-based, defaults to 0)
* `:size` - Number of items per page (usually defaults to 20)
"""
@spec find_fields(keyword()) :: Operation.t()
def find_fields(options \\ []) when is_list(options) do
{pagination, other_options} = pop_pagination(options)
%Operation.JSON{
path: @ep_fields_search,
params: pagination ++ other_options
}
end
@doc """
Creates a metadata field under the given schema.
Executing this operation requires administrator privileges.
"""
@spec create_field(map(), keyword()) :: Operation.t()
def create_field(field, options \\ []) when is_map(field) and is_list(options) do
params = add_parent([], options[:schema_id])
data = normalize_field_payload(field)
%Operation.JSON{
path: @ep_fields,
http_method: :post,
params: params,
data: data
}
end
@doc """
Updates a metadata field.
The API only supports updating the scope note of a field.
"""
@spec update_field(binary(), map()) :: Operation.t()
def update_field(id, updates) when is_nonempty_binary(id) and is_map(updates) do
data = normalize_field_payload(updates)
%Operation.JSON{
path: @ep_fields <> "/" <> id,
http_method: :put,
data: data
}
end
@doc """
Deletes a metadata field.
"""
@spec delete_field(binary()) :: Operation.t()
def delete_field(id) when is_nonempty_binary(id) do
%Operation.JSON{
path: @ep_fields <> "/" <> id,
http_method: :delete,
transformer: fn _ -> :ok end
}
end
@doc """
Fetches a single metadata schema by ID.
"""
@spec fetch_schema(binary()) :: Operation.t()
def fetch_schema(id) when is_nonempty_binary(id) do
%Operation.JSON{path: @ep_schemas <> "/" <> id}
end
@doc """
Lists all metadata schemas of the repository.
This operation can be streamed.
## Options
* `:page` - Page number (0-based, defaults to 0)
* `:size` - Number of items per page (usually defaults to 20)
"""
@spec list_schemas(keyword()) :: Operation.t()
def list_schemas(options \\ []) when is_list(options) do
{pagination, other_options} = pop_pagination(options)
op = %Operation.JSON{
path: @ep_schemas,
params: pagination ++ other_options,
transformer: &Transform.transform_collection(&1, extract: ["_embedded", "metadataschemas"])
}
%{op | stream_impl: &StreamBuilder.new(&1, op, &2)}
end
@doc """
Creates a metadata schema.
"""
@spec create_schema(map(), keyword()) :: Operation.t()
def create_schema(schema, _options \\ []) when is_map(schema) do
%Operation.JSON{
path: @ep_schemas,
http_method: :post,
data: schema
}
end
@doc """
Updates a metadata schema.
"""
@spec update_schema(binary(), map()) :: Operation.t()
def update_schema(id, updates) when is_nonempty_binary(id) and is_map(updates) do
%Operation.JSON{
path: @ep_schemas <> "/" <> id,
http_method: :put,
data: updates
}
end
@doc """
Deletes a metadata schema.
"""
@spec delete_schema(binary()) :: Operation.t()
def delete_schema(id) when is_nonempty_binary(id) do
%Operation.JSON{
path: @ep_schemas <> "/" <> id,
http_method: :delete,
transformer: fn _ -> :ok end
}
end
# Private helpers
defp add_parent(params, parent_id) when is_nonempty_binary(parent_id) do
Keyword.put(params, :schemaId, parent_id)
end
defp normalize_field_payload(map) do
{scope_note, rest} = Map.pop(map, :scope_note)
rest
|> Map.new(fn {k, v} -> {to_string(k), v} end)
|> Map.put("scopeNote", scope_note)
end
end