Entity Client
Methods to create, get and update entities in Preservica. The methods correspond to calls in the Preservica entity API.
Creating a client
The client takes mandatory arguments for the url of the Preservica service and the secret name of the secrets manager secret storing the API credentials.
There is a caching layer which caches the secret value and the API token on disk. The duration of the cache defaults to 15 minutes but can be configured here.
It is also possible to configure the secrets manager endpoint. This can be used for testing or if using private endpoints in a VPC.
These examples use both the FS2 client and the ZIO client
object EntityClients {
import cats.effect.IO
import sttp.capabilities.fs2.Fs2Streams
import uk.gov.nationalarchives.dp.client.EntityClient
import uk.gov.nationalarchives.dp.client.fs2.Fs2Client
import scala.concurrent.duration.*
val preservicaUrl = "https://test.preservica.com"
val secretName = "nameOfSecretsManagerSecretContainingAPICredentials"
val fs2EntityClientWithDefaults: IO[EntityClient[IO, Fs2Streams[IO]]] =
Fs2Client.entityClient(preservicaUrl, secretName)
val fs2EntityClientWithCustomCacheDuration: IO[EntityClient[IO, Fs2Streams[IO]]] =
Fs2Client.entityClient(preservicaUrl, secretName, 30.minutes)
val fs2EntityClientWithCustomSecretsManagerEndpoint: IO[EntityClient[IO, Fs2Streams[IO]]] =
Fs2Client.entityClient(preservicaUrl, secretName, ssmEndpointUri = "https://private.ssm.endpoint")
val fs2EntityClientWithCustomProxy: IO[EntityClient[IO, Fs2Streams[IO]]] =
Fs2Client.entityClient(preservicaUrl, secretName, potentialProxyUrl = Option(URI.create("http://proxy.url")))
}
The client exposes 15 methods
def metadataForEntity(entity: Entity): F[Seq[Elem]]
def getBitstreamInfo(contentObjectRef: UUID): F[Seq[BitStreamInfo]]
def getEntity(entityRef: UUID, entityType: EntityType): F[Entity]
def getEntityIdentifiers(entity: Entity): F[Seq[IdentifierResponse]]
def getUrlsToIoRepresentations(ioEntityRef: UUID, representationType: Option[RepresentationType]): F[Seq[String]]
def addEntity(addEntityRequest: AddEntityRequest): F[UUID]
def updateEntity(updateEntityRequest: UpdateEntityRequest): F[String]
def updateEntityIdentifiers(entity: Entity, identifiers: Seq[IdentifierResponse]): F[Seq[IdentifierResponse]]
def streamBitstreamContent[T](
stream: Streams[S]
)(url: String, streamFn: stream.BinaryStream => F[T]): F[T]
def entitiesUpdatedSince(
dateTime: ZonedDateTime,
startEntry: Int,
maxEntries: Int = 1000
): F[Seq[Entity]]
def entityEventActions(
entity: Entity,
startEntry: Int = 0,
maxEntries: Int = 1000
): F[Seq[EventAction]]
def entitiesPerIdentifier(identifiers: Seq[Identifier]): F[Map[Identifier, Seq[Entity]]]
def getContentObjectsFromRepresentation(
ioEntityRef: UUID,
representationType: RepresentationType,
repTypeIndex: Int
): F[Seq[Entity]]
def addIdentifierForEntity(
entityRef: UUID,
entityType: EntityType,
identifier: Identifier
): F[String]
def getPreservicaNamespaceVersion(
endpoint: String
): F[Float]
Method descriptions
These are descriptions of the steps taken by each method. All methods get an authentication token first, either from the API or the cache.
metadataForEntity
- Call the API to get the
entityInfo
(XML) for the provided reference - Call the API to get the
Identifiers
XML for the entity - Parse XML for the url to the next page of
Identifier
results - if there is a URL, return to step above and keep on until there are not more next page urls
- Return the XML for all the
Identifiers
found - Get the
Links
for the entity - Parse XML for the url to the next page of
Links
results - If there is a URL, return to step above and keep on until there are not more next page urls
- Return the XML for all the
Links
found - Use the
entityInfo
to get the fragment urls from"AdditionalInformation" \ "Metadata" \ "Fragment"
- For each fragment url, get the response
- Return a list of the XML elements found at
"MetadataContainer" \ "Content"
in each response - Call the API to get the
EventActions
XML for the entity- Parse XML for the url to the next page of event action results
- if there is a URL, return to step above and keep on until there are not more next page urls
- Return the XML for all the event actions found
- Check for type of entity passed into this method
- If
CO
- Call the API to get the
Generations
XML for the entity - Parse XML for the URLs to each
Generation
- Use the URLs to get all the
Generations
elements - Parse Generations XML for the URLs to each
Generation
’s bitstream urls - Use the URLs to get all the
Bitstream
elements - Return all metadata in a
CoMetadata
case class
- Call the API to get the
- If
IO
- Call the API to get the URLs of the
Representations
- Extract the
representationType
andgenerationVersion
from each URL - For each group of
representationType
andgenerationVersion
, pass them into theioRepresentations
method to get the XML for each representation - Return all metadata in an
IoMetadata
case class
- Call the API to get the URLs of the
- If neither
IO
, norCO
- Return all metadata in an
StandardMetadata
case class
- Return all metadata in an
getBitstreamInfo
- Get the entity for the provided reference
- Get the first generation url from
"AdditionalInformation" \ "Generations"
- Call the API with this url
- Get all the generations from
"Generations" \ "Generation"
- Send an API request for each of these urls
- Get the bitstream url from
"Bitstreams" \ "Bitstream"
for each of the responses - Call the API with each of these bitstream urls.
- Get the file name, file size and download url for the bitstream from each response.
getEntity
- Get the entity from the provided reference
- Parse the response into the
Entity
class
getEntityIdentifiers
- Get the entity identifiers from the reference
- Call the API for each url returned in the previous step.
- Check for a next page. If there is one, return to step 2 until there is no next page, otherwise, return a
Seq[IdentifierResponse]
getUrlsToIoRepresentations
- Use the IO’s ref in the endpoint’s url
- Call the API to receive a RepresentationsResponse.
- Get all the representations from
"Representations" \ "Representation"
- Filter the representations on the optional
RepresentationType
- Retrieve url(s) from remaining representations
getContentObjectsFromRepresentation
- Use the IO’s ref, representationType and version in the endpoint’s url
- Call the API to receive a RepresentationsResponse.
- Get all the Representation’s Content Objects from
"Representation" \ "ContentObjects" \ "ContentObject"
- Wrap Content Objects in an
Entity
addEntity
- Convert the
AddEntityRequest
case class into XML - Send the XML to the API to create an entity.
- Parse the response and return the newly created reference UUID.
updateEntity
- Convert the
UpdateEntityRequest
case class into XML - Send the XML to the API to update an entity.
- Parse the response and return “Entity was updated”
updateEntityIdentifiers
- Convert the
Seq[IdentifierResponse]
into XML - Send the XML to the API to update the entity identifiers.
- Parse the response and return the original
identifiers
argument.
streamBitstreamContent
- Calls the url from the first argument.
- Passes a stream of the response to the function provided by the second argument.
entitiesUpdatedSince
- Calls the
updated-since
endpoint using the parameters in the arguments. - Converts the response to
Seq[Entity]
and returns
entityEventActions
- Calls the
event-actions
endpoint using the parameters in the arguments. - If there is a next page in the result, call the API until the last page is reached.
- Converts the response to
Seq[EventAction]
and returns
entitiesByIdentifier
- Calls the
by-identifier
endpoint using the parameters in the arguments. - The entities returned by this endpoint don’t contain all the information we need. So for each entity returned, call the
/{ref}
endpoint
addIdentifierForEntity
- Converts the arguments to the XML input
- Calls the
identifiers
endpoint to create an identifier for an entity
getPreservicaNamespaceVersion
- Calls any Entity Preservica endpoint that returns XML
- Returns version number found in namespace