You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@abdera.apache.org by James M Snell <ja...@gmail.com> on 2008/01/26 02:37:05 UTC

TargetBuilder and TemplateTargetBuilder

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

Re: TargetBuilder and TemplateTargetBuilder

Posted by David Primmer <da...@gmail.com>.
I haven't had a chance to look at the details but Vasu and I were just
discussing this and saying that this was a big outstanding need for the
Server. My background is in Python and the class act in that area is
Routes, http://routes.groovie.org/ a powerful package that took
resolving/dispatching and url generation ideas from Ruby on Rails and has
been evolving a lot recently. I don't know a Java package that does this or
is focused in this area but I wanted to suggest it as the best system that I
know of. One of the nicer features is auto-generating rest urls for a given
object:http://routes.groovie.org/manual.html#restful-services

davep

On Jan 25, 2008 5:37 PM, James M Snell <ja...@gmail.com> wrote:

> 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
>

Re: TargetBuilder and TemplateTargetBuilder

Posted by David Primmer <da...@gmail.com>.
I haven't had a chance to look at the details but Vasu and I were just
discussing this and saying that this was a big outstanding need for the
Server. My background is in Python and the class act in that area is
Routes, http://routes.groovie.org/ a powerful package that took
resolving/dispatching and url generation ideas from Ruby on Rails and has
been evolving a lot recently. I don't know a Java package that does this or
is focused in this area but I wanted to suggest it as the best system that I
know of. One of the nicer features is auto-generating rest urls for a given
object:http://routes.groovie.org/manual.html#restful-services

davep

On Jan 25, 2008 5:37 PM, James M Snell <ja...@gmail.com> wrote:

> 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
>