Hi This is a proposal for a new way to add methods to Fedora objects. It is designed to be much simpler than the current system, and content model centric.
I have chosen to call them datastream methods, because they are methods on the object datastreams, not on the object themselves. This, of course, adds further to the discussion about whether or not datastreams are first class objects (which I feel they are) DATASTREAM METHODS: Bound to datastreams in DS-COMPOSITEMODEL, via the extension mechanism. The extension mechanism was introduced with Enhanced Content Models, and will hopefully be a part of Fedora. There will be two kinds of methods, for now called getters and setters. Both invoke some service, and both return the return value from the service. But the setter methods additionally stores the return value in the datastream. As such, we now finally have fedora methods that can modify objects. SECURITY But policy and authentication, I hear you say. These have always been the problem of methods in Fedora. Well, these methods handles that elegantly. To invoke any method, you need to be able to disseminate the datastream, so the policy for getDatastreamDissemination blocks methods overall. Secondly, to use a setter, you need to have the rights for modifyDatastream, so the datastreams are further protected from changes by that policy. All of this is done with the user credentials you used to invoke the method, so it is also done as the correct user (for logging purposes). There will be two new api methods for Fedora, here shown in the REST syntax. The same two methods will exist in the SOAP api. GET /ecm/{pid}/datastreams/{datastream}/methods GET/POST /ecm/{pid}/datastreams/{datastream}/methods/{method}?Param=value... The DS-COMPOSITE-MODEL datastream will now look like this <dsCompositeModel> <dsTypeModel ID="DC"> <form MIME="text/xml"/> <extensions name="METHODS"> <eom:methods xmlns:eom="somenamespace"> <eom:method name="dumpAsJSON" redirect="false"> <eom:public> <eom:docs> Parses the dc terms from this datastream and returns it as JSON. </eom:docs> <eom:type>getter</eom:type> <eom:httpVerb>GET</eom:httpVerb> </eom:public> <eom:resource url="http://${local.fedora.server}/jsondumper" httpmethod="POST"/> <eom:messagebody kind="datastream"/> <eom:downloadName> ${pid}.${datastream}.json </eom:downloadName> </eom:method> </eom:methods> </extensions> </dsTypeModel> </dsCompositeModel> So, reading this: 1. The DC datastream has one method, dumpAsJSON. 2. It is a getter method, so the datastream will not be updated 3. For REST invokation, you should use the GET verb 4. It takes no parameters (more about this later) 5. The service is invoked by POST'in to http://${local.fedora.server}/jsondumper 6. The message body of the post is the datastream contents 7. The downloadname for the resulting file will be ${pid}.${datastream}.json And this is all there is to defining a service. This is all you need to write. PUBLIC INFORMATION Only the information in the public block is shown the user, when he lists the methods. The only way to see the rest is to view the DS-COMPOSITE-MODEL datastream. The information in the public tag is <eom:method name="dumpAsJSON" redirect="false"> <eom:public> <eom:docs> Parses the dc terms from this datastream and returns it as JSON. </eom:docs> <eom:type>getter</eom:type> <eom:httpVerb>GET</eom:httpVerb> </eom:public> </eom:method> DEFAULT PARAMETERS As you could see above, I used the ${xxx} notation. This is taken from ant, which I am reasonably familiar with. ${xxx} is replaced by the value of xxx when the method is invoked. These are the variables that are always and automatically defined ${pid} The object pid ${datastream} The datastream name ${local.fedora.server} The server fedora is running on (dunno if it includes /fedora) ${username} The username, if any, that invoked the method ${formatURI} The format URI for the datastream, if any ${mimetype} The mimetype for the datastream, if any ${contentLocation} The content location for the datastream (is this set for xml datastreams?) ${datastreamState} The state of the datastream ${created} The created date of the datastream ${digest} The checksum of the datastream, if any ${digesttType} The checksum algorithm of the datastream ${controlGroup} The controlgroup of the datastream ${label} The label of the datastream You can define your own as well. <eom:methods xmlns:eom="namespace"> <eom:method name="dumpAsJSON" redirect="false"> <eom:public> <eom:docs>Parses the dc terms from this datastream and returns it as JSON.</eom:docs> <eom:type>getter</eom:type> <eom:httpVerb>GET</eom:httpVerb> </eom:public> <eom:resource url="http://${local.fedora.server}/${type}dumper?OddParam= ${oddparamvalue}" httpmethod="POST"/> <eom:defaultparameter name="type" value="json"/> <eom:defaultparameter name="oddparamvalue" value="123"/> <eom:messagebody kind="datastream"/> <eom:downloadName>${pid}.${datastream}.json</eom:downloadName> </eom:method> </eom:methods> Same example as before, but I have defined two defaultparameters, type and oddparamvalue. They will be replaced into the all the sections before the service is invoked. So, the url is now http://${local.fedora.server}/${type}dumper?OddParam=${oddparamvalue} But when invoked, it will be http://localhost:8080/jsondumper?OddParam=123 Default parameters are not very powerful, as you could just as easily have written out the value in the url. But they help you not having to repeat yourself. USER PARAMS Now, for the user specified params <eom:methods xmlns:eom="namespace"> <eom:method name="dumpAsJSON" redirect="false"> <eom:public> <eom:docs>Parses the dc terms from this datastream and returns it as JSON.</eom:docs> <eom:type>getter</eom:type> <eom:httpVerb>GET</eom:httpVerb> <eom:userparameter name="oddparamvalue" value="123"/> </eom:public> <eom:resource url="http://${local.fedora.server}/${type}dumper?OddParam= ${oddparamvalue}" httpmethod="POST"/> <eom:defaultparameter name="type" value="json"/> <eom:messagebody kind="datastream"/> <eom:downloadName>${pid}.${datastream}.json</eom:downloadName> </eom:method> </eom:methods> As you can see, the oddparamvalue is no longer a defaultparameter. It is now a userparameter. The user parameter has a value, which is the default value, if the user does not set the parameter. To invoke this service with the param set, use GET /ecm/{pid}/datastreams/DC/methods/dumpAsJSON?oddparamvalue=234 If not set, the 123 value will be used for the substitution. HTTPHEADERS You can set the header parameters fedora should use when invoking the remote service. All http headers are allowed here. <eom:methods xmlns:eom="namespace"> <eom:method name="dumpAsJSON" redirect="false"> <eom:public> <eom:docs>Parses the dc terms from this datastream and returns it as JSON.</eom:docs> <eom:type>getter</eom:type> <eom:httpVerb>GET</eom:httpVerb> <eom:userparameter name="oddparamvalue" value="123"/> </eom:public> <eom:resource url="http://${local.fedora.server}/${type}dumper?OddParam= ${oddparamvalue}" httpmethod="POST"/> <eom:defaultparameter name="type" value="json"/> <eom:messagebody kind="datastream"/> <eom:header name="Content-Type" value="${mimetype}"/> <eom:downloadName>${pid}.${datastream}.json</eom:downloadName> </eom:method> </eom:methods> This is the same example as the previous, except I have added the header tag. It sets the http header "Content-Type" to the value of the datastream mime type. As you can see, you can use variable substitution in headers as well. This can also be used for hardcoded authentication headers for invoking the service. MESSAGE BODY The message body is only used when the remote service is invoked with a POST request. The message body can be one of three types * Datastream: <eom:messagebody kind="datastream"/> The datastream dissemination is sent as the body * Disable: <eom:messagebody kind="disable"/> No message body is sent (or body length 0) * Text: <eom:messagebody kind="text"> This is the text to sent as body. I can use variable substitution in here, so here is the content location: ${contentlocation} </eom:messagebody> With CDATA[[ tags you can even put xml in there. As you can use variable substitution, with both default parameters, user parameters and predefined parameters you can express some quite complex dynamic bodies. REDIRECT You might have noticed that I always had the redirect attribute to false. <eom:method name="dumpAsJSON" redirect="false"> Redirect is a nifty little feature, only usable for getter methods. Rather than streaming the response through Fedora, the client receives a HTTP redirect response, to the service url (after the substitution have been done, of course). It has been added for getters on big external datastreams, that should not be streamed through Fedora. But there is another feature of redirect. Since the request is redirected, the client can authenticate itself with the service, rather than having Fedora do it (or not do it, which is probably what will be done). Redirect can, of course, not be used with setters, as Fedora cannot intercept the return body to store it in the datastream. Just to finish of, here is an appetizer on what you can do with this functionality <dsCompositeModel> <dsTypeModel ID="RELS-EXT"> <extensions name="METHODS"> <eom:methods xmlns:eom="somenamespace"> <eom:method name="getAsJSON" redirect="false"> <eom:public> <eom:docs>Parses the datastream and returns it as json </eom:docs> <eom:type>getter</eom:type> <eom:httpVerb>GET</eom:httpVerb> </eom:public> <eom:resource url="http://${local.fedora.server}/${type}dumper" httpmethod="POST"/> <eom:defaultparameter name="type" value="json"/> <eom:messagebody kind="datastream"/> <eom:header name="Content-Type" value="${mimetype}"/> </eom:method> <eom:method name="storeAsJSON" redirect="false"> <eom:public> <eom:docs>Parses the message body as JSON, converts it to RDF, and stores it in the datastream</eom:docs> <eom:type>setter</eom:type> <eom:httpVerb>POST</eom:httpVerb> <eom:userparameter name="jsonmimetype" value="application/json"/> </eom:public> <eom:resource url="http://${local.fedora.server}/${type}dumper" httpmethod="POST"/> <eom:defaultparameter name="type" value="rdf"/> <eom:messagebody kind="user"/> <eom:header name="Content-Type" value="${jsonmimetype}"/> </eom:method> </eom:methods> </extensions> </dsTypeModel> </dsCompositeModel> This is the definition of two methods on the RELS-EXT datastream. One getter, and one setter. The getter allows you to get the datastream as JSON. The setter allows you to store json, which it converts to rdf before storing. I would like to hear peoples response to getting this kind of functionality in Fedora. If people feel it should not be in Fedora, I will implement it as a standalone service. There should be no problem (except a little performance problem) in using GET/POST http://someserver.com/fedora/objects/{pid}/datastreams/{datastream}/methods/{method}?Param=value... or GET/POST http://someserver.com/ecm/{pid}/datastreams/{datastream}/methods/{method}?Param=value... Regards Asger ------------------------------------------------------------------------------ The Planet: dedicated and managed hosting, cloud storage, colocation Stay online with enterprise data centers and the best network in the business Choose flexible plans and management services without long-term contracts Personal 24x7 support from experience hosting pros just a phone call away. http://p.sf.net/sfu/theplanet-com _______________________________________________ Fedora-commons-developers mailing list Fedora-commons-developers@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/fedora-commons-developers