Introduction

This thought experiment is intended to chip away at the question "What would happen if the Content CMA supported read/write service methods on Fedora objects"?   Specifically, let us take a look at the Atom Publishing Protocol(APP) as a concrete example.  Can we use a read/write CMA to do creative things with the APP?  Do we like the end result?  If so, do we have any useful suggestions for the design of a fully read/write CMA?  Please note that this is just a thought experiment, and not a proposal. 

The scenario

Suppose that we wish to build a repository that contained two different kinds of atom feeds.  Let's say that we want first type of feed to allow us to see all datastreams (and versions) in an object, in much the same fashion as the current atom serialization.  For the second, we want to represent a higher level concept: image collections.  Clearly, there will be situations where some objects contain BOTH feeds.  We want the feeds to be orthogonal so that this is not a problem.  Let's go into each situation in a bit more detail:

Feed 1: Datastreams in Every Object

For feed 1, we want to represent the structure of a Fedora object, in terms of datastreams, as an Atom feed.  In addition, we would like to use the atom publishing protocol to add, remove, or update datastreams to an object.  Specifically, let's suppose that we would like the following characteristics from our datastreams feed:

  1. The atom feed for an object shall have a URI, and this shall be the collection feed URI as specified in the atom publishing protocol.
  2. All datastreams and datastream versions shall be represented in the atom feed for an object
  3. In accordance with the APP, new datastreams may be created, deleted, or updated in this feed
    1. The client should be able to specify the desired datastream ID when creating a new datastream
    2. Once a specific datastream version exists (e.g bound to the point in time it was created), it can be deleted, but not edited.

Feed 2: Atomistic Image Collection 

For feed 2, we want to allow for the repository to contain multiple image collections, extending the functionality of the demo image collection.  Each image collection is represented by its own object in the repository, as are individual image items.  Collection membership is determined by the presence of an 'isMemberOf' relationship from an image to a collection.  Specifically, let's suppose that we wanted the following characteristics:

  1. We want to extend the functionality provided by the demo image collection by allowing these collections to be modified using the atom publishing protocol.
    1. Existing demo SDefs and SDeps from the image collection remain unchanged
    2. Images added/modified via AtomPub are considered FULL_SIZE
  2. There exists a ServiceDocument that enumerates all the image collections in the repository and their collection feed URIs (as provided by the APP)
  3. Each image collection has a collection feed URI
  4. In accordance with the APP images may be added, removed, or replaced through through this feed
    1. Adding an object to the feed implies adding a new object to the repository - but the client shall have no awareness of this process
    2. Deleting an object from the feed implies purging the image object from the repository - but the client shall have no awareness of this process

A Possible Direction

General concepts 

It appears that there may be three general 'types' of object that are relevant as far as our APP needs are concerned:  Objects that represent collection feeds, objects that represent items in a collection, and objects that represent the set of all collections.  Note:  In Feed 1, since the model is not atomistic, we really only have objects that represent entire collections.  Let's see if this matters later on.  For now, though, let's represent these 'types' as SDefs, with the following structure:

SDef pid:   atom:Collection
method:     service # APP Service document for one collection (read only)
method:     feed # Atom Collection feed (read/write as per APP)
SDef pid:   atom:Item
method:     media # Media Resource for this item
                  # may or may not have content, read/write
method:     entry # Atom entry for this item (read/write)
SDef pid:   atom:Domain
method:     feeds # APP Service document for all collections (read only)

Additionally, let's assume that Fedora's REST API exposed URIs for the methods expressed in these SDefs as follows:

http://(fedora.server)/services/(object-pid)/(sdef-pid)/(method)[/additional]

...where  [/additional] could be parameters, or additional path elements in the URI.

For example, one of our service methods above would look like http://example.org/fedora/services/demo:SmileyStuff/atom:Collection/entries

 
The service methods (exposed as URIs in the REST API) behave as follows.  The intent is to provide a representation of many concepts detailed in the APP, so the descriptions here are abbreviated.

atom:Collection/service

GET - retrieves a Service Document that describes the single feed in the collection

atom:Collection/feed

GET - retrieves an atom feed of the items in the collection

POST - create a entry or media item

atom:Item/media

This is the URI of the media resource.  According to the APP, there will be a corresponding media link entry in the feed.  The edit-media link in the entry will point to this URI.

GET - Get the media for an item (image, text, etc).  If the item does not have media, it makes sense for this to return a 404

PUT - Replace the media for this item 

atom:Item/entry
This is the URI of an individual atom entry - the feed is composed of these. 

GET - Get the atom entry

PUT - Modify the information contained in an atom entry

atom:Domain/feeds

GET - Retrieves a Service Document describing all the collection feeds for a particular domain (defined later).   Essentially, this is a concatination of the atom:Collection/service documents of all collections in the domain.

Domains 

The APP provides Service Documents as a means of discovery for feeds.  A Service Document URI enumerates all the feeds within (and possibly groups them into "workspaces").   In a repository environment as diverse as Fedora, it does not seem to make sense to have a single Service Document enumerating ALL the feeds.  In our example, we have two mostly unrelated scenarios: atom feeds for every object, and atom feeds for image collection objects.   The composition and semantics of these feeds differ.   Thus, let us use the word "domain" to represent the different information spaces represented by these feeds.

If we want different atom-feed domains to remain separate, then we need to expand upon the general SDefs introduced above.   Some possibly valid strategies include

  1. Define new SDefs for each domain, conforming to the signatures of atom:Collection and atom:Item, but having distinct identities (e.g. http://example.org/fedora/services/demo:X/atom:ImageCollection/feed)
  2. Add parameters to each method/URI indicating domain (e.g. http://example.org/fedora/services/demo:X/atom:Collection/feed?domain=ImageCollection)
  3. Add additional path elements to the URI indicating domain(e.g. http://example.org/fedora/services/demo:X/atom:Collection/feed/ImageCollection/)

Solving Our Scenerio

In continuing this thought experiment, let's proceed by defining domain-specific SDefs representing our two feeds, and see where that gets us. 

SDef pid:   thought-exp:ImageCollection
method:     service # APP Service document for one image collection
method:     feed    # atom Image Collection feed
---
has model:  atom:DomainModel  # This model has Sdef atom:Domain, so this object
                              # has method atom:Domain/feeds, which list all
                              # image collection feeds
SDef pid:   thought-exp:ImageItem
method:     media # Image Resource for this item
method:     entry # Atom entry for this item
SDef pid:   thought-exp:Datastreams
method:     service # APP Service document for one object's datastream collection
method:     feed    # atom feed listing all datastreams + versions
---
has model:  atom:DomainModel  # This model has Sdef atom:Domain, so this object
                              # has method atom:Domain/feeds, which list all
                              # object feeds (may be dangerous!!!)
SDef pid:   thought-exp:Datastream
method:     media # Datastream content Resource for this item
method:     entry # Atom entry for this datastream
SDef pid:   atom:Domain
method:     feeds # APP Service document for all collections

These objects would then define the following URIs and interaction model:

http://example.org/fedora/services/thought-exp:ImageCollection/atom:Domain/feeds

GET - Service Document containing all image collection feeds.

<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
  <workspace>
    <atom:title>Image Collections</atom:title>
    <collection href="http://example.org/fedora/services/demo:SmileyStuff/thought-exp:ImageCollection/feed">
      <atom:title>Smiley Stuff Images</atom:title>
      <accept>image/jpeg</accept>
    </collection>
    <collection href="http://example.org/fedora/services/demo:FrownyStuff/thought-exp:ImageCollection/feed" >
      <atom:title>Frowny stuff</atom:title>
      <accept>image/png</accept>
      <accept>image/jpeg</accept>
      <accept>image/gif</accept>
    </collection>
  </workspace>
</service>


http://example.org/fedora/services/thought-exp:Datastream/atom:Domain/feeds

GET - Service Document containing all object datastream feeds.  This could possibly be a very large list, resulting in a ginormous Service Document  Unlike atom feeds, I don't believe one can implement pagination for this document. 

http://example.org/fedora/services/(PID)/thought-exp:ImageCollection/service

GET - Service document for one image collection.  Service documents may enumerate the acceptable content types, so an image collection may list off supported image formats (such as image/png, image/jpeg, etc

<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
  <workspace>
    <atom:title>Image Collections</atom:title>
    <collection href="http://example.org/fedora/services/demo:SmileyStuff/thought-exp:ImageCollection/feed">
      <atom:title>Smiley Stuff Images</atom:title>
      <accept>image/jpeg</accept>
    </collection>
  </workspace>
</service>


http://example.org/fedora/services/(PID)/thought-exp:ImageCollection/feed

GET - Get an atom feed of all images in a collection represented by the PID object.  

<feed xmlns="http://www.w3.org/2005/Atom">
 <title>Smiley Stuff Images</title>
 <link href="http://example.org/fedora/services/demo:SmileyStuff/thought-exp:ImageCollection/feed" rel="self"/>
 <updated>1980-03-20T09:15:02Z</updated>
 <author>
   <name>Chis Wilper</name>
 </author>
 <id>info:fedora/demo:SmileyStuff/thought-exp:ImageCollection</id>

 <entry>
   <title>Smiley Toilet Brush</title>
   <id>info:fedora/demo:SmileyToiletBrush/thought-exp:ImageItem</id>
   <updated>1979-10-07T17:17:08Z</updated>
   <content type="image/png"
    src="http://example.org/fedora/services/demo:SmileyToiletBrush/thought-exp:ImageItem/media"/>
   <link rel="edit-media"
    href="http://example.org/fedora/services/demo:SmileyToiletBrush/thought-exp:ImageItem/media" />
   <link rel="edit"
    href="http://example.org/fedora/services/demo:SmileyToiletBrush/thought-exp:ImageItem/entry" />
 </entry>

</feed>

POST - Accept only media items (i.e. images in supported formats).  A POSTed image would cause the following to happen:

  1. Create Fedora object for new item created
    1. If the 'Slug' header is defined, possibly assign object a NEW_PID derived from that
  2. Return an ATOM entry found at: http://example.org/fedora/services/(NEW_PID)/thought-exp:ImageItem/entry

http://example.org/fedora/services/(PID)/thought-exp:ImageItem/media

GET - Get an image

PUT - Replace an image.  The item's 'entry' link will reflect the update

http://example.org/fedora/services/(PID)/thought-exp:ImageItem/entry

GET - Get the entry

<entry xmlns="http://www.w3.org/2005/Atom">
   <title>Smiley Beer Glass</title>
   <id>info:fedora/demo:SmileyBeerGlass/thought-exp:ImageItem</id>
   <updated>1979-10-07T17:17:08Z</updated>
   <content type="image/png"
    src="http://example.org/fedora/services/demo:SmileyBeerGlass/thought-exp:ImageItem/media"/>
   <link rel="edit-media"
    href="http://example.org/fedora/services/demo:SmileyBeerGlass/thought-exp:ImageItem/media" />
   <link rel="edit"
    href="http://example.org/fedora/services/demo:SmileyBeerGlass/thought-exp:ImageItem/entry" />
 </entry>

PUT - Replace entry metadata

http://example.org/fedora/services/(PID)/thought-exp:Datastreams/service

GET - Service document for one object.  Service documents may enumerate the acceptable content types.. perhaps it makes sense to introspect in the object's models, but it may be more flexible not to enumerate anything at all, if that's possible.

http://example.org/fedora/services/(PID)/thought-exp:Datastreams/feed

GET - Get an atom feed of all datastreams and versions represented by the PID object.

GET - Get an atom feed of all images in a collection represented by the PID object.  

<feed xmlns="http://www.w3.org/2005/Atom">
 <title>demo:SmileyBeerGlass datastreams</title>
 <link href="http://example.org/fedora/services/demo:SmileyBeerGlass/thought-exp:Datastreams/feed" rel="self"/>
 <updated>1980-03-20T09:15:02Z</updated>
 <author>
   <name>Chis Wilper</name>
 </author>
 <id>info:fedora/demo:SmileyBeerGlass/thought-exp:Datastreams</id>

 <entry>
   <title type="text">RELS-EXT</title>
   <id>info:fedora/demo:SmileyBeerGlass/thought-exp:Datastream/RELS-EXT</id>
   <updated>1979-10-07T17:17:08Z</updated>
   <content type="application/rdf+xml"
    src="http://example.org/fedora/services/demo:SmileyBeerGlass/thought-exp:Datastream/media?id=RELS-EXT"/>
   <link rel="edit-media"
    href="http://example.org/fedora/services/demo:SmileyBeerGlass/thought-exp:Datastream/media?id=RELS-EXT" />
   <link rel="edit"
    href="http://example.org/fedora/services/demo:SmileyBeerGlass/thought-exp:Datastream/entry?id=RELS-EXT" />
 </entry>

 <entry xmlns:thr="http://purl.org/syndication/thread/1.0">
   <title type="text">RELS-EXT.0</title>
   <id>info:fedora/demo:SmileyBeerGlass/thought-exp:Datastream/RELS-EXT.0</id>
   <updated>1979-10-07T17:17:08Z</updated>
   <thr:in-reply-to ref="info:fedora/demo:SmileyBeerGlass/thought-exp:Datastream/RELS-EXT"/>
   <content type="application/rdf+xml"
    src="http://example.org/fedora/services/demo:SmileyBeerGlass/thought-exp:Datastream/media?id=RELS-EXT&version=1979-10-07T17:17:08Z"/>
   <link rel="edit"
    href="http://example.org/fedora/services/demo:SmileyBeerGlass/thought-exp:Datastream/entry?id=RELS-EXT&version=1979-10-07T17:17:08Z" />
 </entry>
</feed>

POST - Accept datastream content.  POSTed data would cause the following to happen:

  1. Create a new datastream
    1. If the 'Slug' header is defined, assign object a datastream ID based on (identical to?) that.
  2. Return an ATOM entry found at: http://example.org/fedora/services/(PID)/thought-exp:Datastream/entry?id=DSID?version=XYZ, where 'DSID' is the datastream ID and 'version' is the datastream's version.  entry shall have edit-media link pointing to unversioned datastream media URI.

http://example.org/fedora/services/(PID)/thought-exp:Datastream/media?id=DSID(&version=2008...)

GET - Get the datastream content

PUT - Put new datastream content (return an error if version is specifed??)

http://example.org/fedora/services/(PID)/thought-exp:Datastream/entry?id=DSID(&version=2008...)

GET - Get entry medatata

PUT -  Modify entry metadata (Not sure what consequences are...)

The Other objects... 


So far, we've really only discussed the public "interfaces" of AtomPub in a writable CMA - the SDefs, URIs, and data formats.  Let us now take a look at all CMA and instance objects together, and see if we can map our desired functionality on to them.

Image item model:

pid:                       demo:DualResImage
relationship.hasService:   thought-exp:ImageItem # New Atom functionality
relationship.hasService:   demo:DualResolution   # Original image collection functionality
relationship.hasModel:     fedora-system:ContentModel-3.0
DS-COMPOSITE-MODEL:        datastream: FULL_SIZE # from original demo:DualResImage
                           datastream: MEDIUM_SIZE # from original demo:DualResImage
                           datastream: RELS-EXT:  # from original demo:DualResImage
                           datastream: DC # from original demo:DualResImage

Image item instance (one per image)

pid:                      [item PID]
datastream:               MEDIUM_SIZE
datastream:               FULL_SIZE
datastream:               DC
relationship.isMemberOf   [collection PID] # de facto, see image collection demo objects
relationship.hasModel:    demo:DualResImage

Image item SDef:

pid:                    thought-exp:ImageItem
method:                 service # APP Service document for one image collection
method:                 feed    # atom Image Collection feed
relationship.hasModel   atom:DomainModel # to have atom:Domain/feeds
relationship.hasModel   fedora-system:ServiceDefinition-3.0

Image item SDep:

pid:      thought-exp:ImageItemInstanceImpl
relationship.isDeploymentOf: thought-exp:ImageItem
relationship.isContractorOf: demo:DualResImage
relationship.hasModel: fedora-system:ServiceDeployment-3.0

Image collection model:

pid:                       demo:DualResImageCollection
relationship.hasService:   thought-exp:ImageCollection   # Adds atom collection functionality
relationship.hasModel:     fedora-system:ContentModel-3.0
DS-COMPOSITE-MODEL:        datastream: thought-exp.imageCollection.ATOM_SERVICE
                           datastream: QUERY # from original demo:DualResImageCollection
                           datastream: XSLT  # from original demo:DualResImageCollection
                           datastream: LIST  # from original demo:DualResImageCollection

Image collection instance:

pid:  [collection PID]
relationship.hasModel      demo:DualResImageCollection
datastream:                QUERY
datastream:                XSLT
datastream:                LIST
datastream:                thought-exp.ImageCollection.ATOM_SERVICE

atom image collection SDef:


atom image collection SDep:


page is unfinished.  Need to put in discussion, questions/implications, and basic conclusion as to whether this makes sense, and if it truly adds any value to, say, an external APP service.

  • No labels