Skip to end of metadata
Go to start of metadata

Some rough notes on how a CollectionObject service might be modeled in a resource-oriented architecture (ROA) manner:

Assumptions

About CollectionObjects

  • A CollectionObject represents one of the "managed" objects of a Collection.
  • A CollectionObject is a conceptual reference to some real-world entity.
  • A CollectionObject may be entirely digital, such as a digital video or image file.
  • A CollectionObject may have sub-objects associated with it.
  • A CollectionObject's sub-objects may not be created until a time that is much later than initial object creation.
  • A CollectionObject's sub-objects may be physical or digital (e.g. each of the pieces of a chessboard; a fragment chipped from a bone by museum staff, to facilitate scientific study, following object entry; or a photo, video, imaging scan, or another similar digital image of the real-world entity, which may itself be physical or digital).
    ...

About Related Entities

  • A Resource - which may include images, documents, letters, etc. is tracked as an entity in the system, but is not a CollectionObject.
  • A Resource may be associated with a CollectionObject.
  • A Collection - a "grouping largely for administrative workflow," within which any particular CollectionObject might be assigned.
    ...

URIs (URLs)

Arbitrary URLs representing CollectionObjects, including their parent containers, and their children:

Top-level container (a view onto the CollectionObject space, independent of Collection:

/collectionobjects/
/collection-objects/
/collectionObjects/
/CollectionObjects/

In the examples below, the first of those names is used:

/collectionobjects/{identifier} - Addresses the collection

Operations

Some of the simplest possible operations, for a "Hello, World" Release 0.1 demo, might look like this:

Add a New CollectionObject

Implementation pseudocode (generally repeated in operations below, but perhaps not always detailed there):

At the client layer:

  • Send an HTTP POST request to /collectionobjects/
    with an entity body representing the CollectionObject schema.

    This may be done using any HTTP client library, a language-specific proxy, a language-specific client library (akin to Google's GData Client Library), or some other mechanism.

At the service layer:

  • The schema is validated for:
    • Required fields
    • Other schema-specific validation rules
  • A new, unique system identifier is assigned to the object.
  • One or more types of new, unique instance-specific (museum) IDs are assigned to the record, based on a pattern or other set of rules for granting IDs.
  • The new CollectionObject record is stored in the database.
  • An HTTP response is returned to the client, which will include an 'OK' status code (200), a success result code and message, and (potentially) a representationn of the just-added record, which will include the values of any IDs that were added to the record in the service layer steps above.

Note that this simple example doesn't deal with authentication (AuthN) or authorization (AuthZ), which are currently out of scope for Release 0.1, although we'll need to think about how that will be managed from an early stage.

At the client layer:

  • The client uses its HTTP client library (or proxy or client library) checks the HTTP status code of the response.
    If it is 200 (or an equivalent success result from a proxy or client library) ...
  • It reads the result code from within the entity body, to check whether the new CollectionObject was successfully stored, or whether an error occurred within the service layer, preventing that action from taking place. The client can read the result code (if the entity body of the response is in XML) using XPath or XQuery, or generic XML parsing. The client branches to perform its appropriate next steps, depending on the result code returned.
    If it is a 400 series error (typically client error, such as non-existing record being requested, client access not authorized, etc.), or 500 series error, representing a service error (such as a web server/web application container being down), the client will need to handle this accordingly.

Read an Existing CollectionObject

Some possible ways to address a read request to a particular CollectionObject:

At the client layer:
Send an HTTP GET request to one or more of the patterns below, depending on which of these the service may support:

  • /collectionobjects/{identifier}, where identifier is an instance of a unique pattern representing a system identifier, or one or more instance-specific (museum) IDs.
  • /collectionobjects/systemid/{identifier}, where identifier is an instance of a unique system ID.
  • /collectionobjects/{idtype}/{identifier}, where identifier is an instance of a unique ID within the idtype ID space.
  • /collectionobjects/collectionid/{identifier}, where identifier is an instance of a unique ID within a single, instance-specific (museum) ID space.

At the service layer:

  • The identifier is extracted from the request URL pattern.
  • Depending on the type of container in which the request is being made, the equivalent of a SELECT on a particular index field (column) will be performed in the appropriate database table.
  • If a record (row) is returned, an HTTP response is returned to the client, which will include an 'OK' status code (200), a success result code and message, and a representation of the record.
  • If no records (rows) are returned, an HTTP response is returned to the client, which will include a 'NOT FOUND' status code (404), an error result code and message, and an empty (blank) representation of the record.

Read Multiple Existing CollectionObjects

Some possible ways to address a 'read multiple' request to a container of CollectionObjects. This is a variant case on the 'read' request above.

Send an HTTP GET request to /collectionobjects/systemid/, to return hyperlinks to each CollectionObject.

Use several of the URL conventions above that include a single identifier, except wherever a single identifier is listed, substitute this pattern:

{min-identifier}:{max-identifier}

where {min-identifier} is the first of an in-some-manner sequential set of IDs, and {max-identifier} is the last of that set of IDs. (The colon and semi-colon are used as separators for sequential and non-sequential ranges, respectively, in some RESTful best practices discussions.) Examples:

/collectionobjects/systemid/cspaceprefix-2306:cspaceprefix-4881
/collectionobjects/systemid/cspaceprefix-20ffa3:cspaceprefix-210b39

We'll need to think through the cases where there may be large numbers (e.g. tens or hundreds of thousands) of records returned, either from an open-ended request that doesn't specify a range of IDs, or a request that specifies a wide range of IDs.

On Beyond Release 0.1

Some ROA examples of how one might query/refer to the properties of a CollectionObject:

Get all (historical and current) locations for a CollectionObject:

/collectionobjects/{identifier}/locations

Returns a representation of one or more CollectionObjectLocation (relation) objects, or links to same (TBD).

Get or set the current location for a CollectionObject:

/collectionobjects/{identifier}/locations/current
and/or
/collectionobjects/{identifier}/location

With a GET request, returns a representation to the most recent CollectionObjectLocation (relation) object.

with a POST or PUT request, replaces or updates the most recent CollectionObjectLocation (relation) object. This might be implemented by adding an 'end timestamp' to the most recent CollectionObjectLocation object, then creating a new CollectionObjectLocation object with a 'start timestamp' matching the 'end timestamp' of the previously-current object. This would also trigger an audit trail item and a 'location moved' message.

  • No labels