abdera-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From James M Snell <jasn...@gmail.com>
Subject TargetBuilder and TemplateTargetBuilder
Date Sat, 26 Jan 2008 01:37:05 GMT
Up to this point, providers/collectionadapters have had to handle all of 
the details in constructing URIs for feeds and entries.  The process was 
cumbersome and problematic for many reasons.  As part of the server 
refactoring, today I checked in a new interface called TargetBuilder (I 
know the name sucks) whose job it is to construct urls on behalf of the 
collection adapter.

Provider implementations provide the TargetBuilder implementation, which 
is accessed by the CollectionAdapter via the RequestContext.  There is 
currently one TargetBuilder implementation, TemplateTargetBuilder, which 
uses the URI Template code in the i18n module to construct URLs.

The DefaultProvider and BasicProvider each use their own internal 
TargetBuilder implementations.  It is possible for developers to 
override those implementations but it's not likely that they will.

Custom provider implementations will need to provide their own Target 
Builder implementations,

For instance, if you look at 
/branches/server_refactor_all/server/src/test/java/org/apache/abdera/protocol/server/test/custom/CustomProvider.java,

you will see:

     setTargetBuilder(
       new TemplateTargetBuilder()
         .setTemplate(TargetType.TYPE_SERVICE, "{target_base}/atom")
         .setTemplate(TargetType.TYPE_COLLECTION, 
"{target_base}/atom/{collection}{-opt|?|q,c,s,p,l,i,o}{-join|&|q,c,s,p,l,i,o}")
         .setTemplate(TargetType.TYPE_CATEGORIES, 
"{target_base}/atom/{collection};categories")
         .setTemplate(TargetType.TYPE_ENTRY, 
"{target_base}/atom/{collection}/{entry}")
         .setTemplate(OpenSearchFilter.TYPE_OPENSEARCH_DESCRIPTION, 
"{target_base}/search")
     );

Then, in 
/branches/server_refactor_all/server/src/test/java/org/apache/abdera/protocol/server/test/custom/SimpleAdapter.java,

you will see:

   private String getEntryLink(RequestContext request, String entryid) {
     Map<String,String> params = new HashMap<String,String>();
     params.put("collection", 
request.getTarget().getParameter("collection"));
     params.put("entry", entryid);
     return request.resolveIri(TargetType.TYPE_ENTRY, params);
   }

Note that the collection adapter calls the RequestContext, which uses 
the target builder to construct the URI.

Because the target builder is using the URI Template implementation, the 
input parameter in getEntryLink(..) can be a Map<String,Object>, a 
org.apache.abdera.i18n.templates.Context implementation, or any java 
bean with public getters.  For instance, this would work also:

   public class Foo {
     public String getCollection() {return "feed";}
   }
   private String getEntryLink(RequestContext request, String entryid) {
     return request.resolveIri(TargetType.TYPE_ENTRY, new Foo());
   }

The TemplateTargetBuilder provides a number of built-in variables that 
can be used within the URI Templates.

{request_context_path} = the servlet context path of the current request
{request_content_type} = the mime content type of the current request
{request_uri} = the request uri (relative) of the current request
{request_resolved_uri} = the absolute request uri of the current request
{request_language} = the value of the current requests Accept-Language
{request_charset} = the value of the current requests Accept-Charset
{request_user} = the name of the authenticated user
{target_identity} = the value of Target.getIdentity()
{target_path} = the subset of the request uri used to identify the
                 target
{target_base} = the root of the target_path, usually the contextpath +
                 the servlet path
{request_parameter_[name]} = the value of
                              requestContext.getParameter("[name]")
{request_attribute_[name]} = the value of
                              requestContext.getAttribute(Scope.REQUEST,
                                                          "[name]")
{session_attribute_[name]} = the value of
                              requestContext.getAttribute(Scope.SESSION,
                                                          "[name]")
{request_header_[name]} = the value of
                           requestContext.getHeader("[name]")
{target_parameter_[name]} = the value of Target.getParameter("[name]")

These variables can be used anywhere within any of the URI Templates 
defined on TemplateTargetBuilder.

DefaultProvider and BasicProvider both use the TemplateTargetBuilder 
internally, but define a number of default templates.  To add your own 
templates (or to override the defaults), you need to subclass the provider..

   public class MyProvider extends DefaultProvider {
     public MyProvider() {
       TemplateTargetBuilder ttb =
         (TemplateTargetBuilder) getTargetBuilder(null);
       ttb.setTemplate("foo", "{target_base}/my/custom/template");
     }
   }

Then, in your CollectionAdapter, you can call...

   request.resolveIri("foo", null);

Anyway, the code is checked into the server_refactor_all branch.  As 
always, comments/feedback are welcomed and requested.

- James

Mime
View raw message