You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Daniela Gehle <d....@levigo.de> on 2001/10/16 12:08:56 UTC

[RT] Flow Navigation

Hi again,

first of all I'd like to point out that I'm overwhelmed by your interest
in the Flowmap topic and I'd like to thank all of you for your feedback
and suggestions.

I still owe you a description of the Flow Navigation Transformer I
mentioned in last week's "Flowmaps Revisited" RT. 

Here it is:

A further component closely connected to flow handling and the
TransitionMap is the FlowNavigation Transformer.

A quick reminder: Flow Navigation refers to states in a flow. A Flow
Navigation link leads from a page (=visible state) to a state that is
part of a flow (usually, but not necessarily a hidden state). In other
words: the Flow Navigation Link represents a transition leading away
from the current page. Now you can imagine that there is not only one or
two transitions that can be followed from a page, but a couple of them,
and - even worse - some or all of them requiring specific parameters.

As you can see, it would be very inconvenient to specify all these Flow
Navigation links manually, and therefore our goal is to provide an
automatic way to generate these Flow Navigation links. Of course this
mechanism does only work for pages that are part of a flow. 

Now, what is a Flow Navigation link?

- In the end, it's just an HTML-conform URL like 
  <a href="result-list?LOGOUT=true"/> or 
  <a href="result-list?SHOW=true&articleID=12345"/>. 
  (Of course, other output formats than HTML are supported as well.)

- At the beginning, it's nothing more than information hidden in the 
  Transition Map that has to be extracted by an "intelligent" mechanism 
  (which might, as proposed here, be implemented in a Transformer). 

- In the middle, it is generic XML elements that are inserted into the 
  XML data at specified places. 

Sounds easy, doesn't it? Now, how do the involved components work
together? 

We can draw a simple picture of the processing pipeline:

XML template 
    |
    v
(Generator) 
    |
    v
XML raw data (1)
    |
    v
(FlowNavigationTransformer)    <-- TransitionMap (2)
    |
    v
XML data with flow navigation elements integrated into the data
structure (3)
    |
    v
(XSL Transformation)  
    |
    v
(Serializer)
    |
    v
Final page, e.g. HTML (4)

The Transition Map (2) contains the necessary information for the Flow
Navigation element generation in the parameter definitions tied to the
transitions. The FlowNavigation Transformer adds these transition
parameters to the generated XML raw data (1) and generates the Flow
Navigation elements for the current page and outputs XML data containing
generic Flow Navigation elements (3). Then the usual stylesheet
transformation and serialization process takes place, resulting in the
final page (4).

Let's make a simple example:
Take a page that lists articles for a specific topic. (This one is
borrowed from the Flowmap RT example.) The page, named "result-list",
might look like this:

----------------------------------------------------------------
| -> logout		                                       |
| -> choose topic                                              |
| -> search articles                                           |
|--------------------------------------------------------------|
| Article Headline	| date		| author               |
| Nothing important	| 01.09.2001	| MR	->show  ->edit |
| More nonsense today 	| 05.09.2001	| JH	->show  ->edit |
| Even more gaga!	| 12.09.2001	| DG	->show  ->edit |
----------------------------------------------------------------

The page starts with three navigational links to other pages:

-> logout 	leads to <a href="result-list?LOGOUT=true"/>
-> choose topic	leads to <a href="result-list?CHOOSETOPIC=true"/>
-> search articles leads to <a href="result-list?NEWSEARCH=true"/>

followed by a table displaying each of the news articles. There are two
links for each of these articles, ->show  and ->edit. For the first
article, for example, these links look like this:

->show 	leads to <a href="result-list?SHOW=true&articleID=12345"/>
->edit	leads to <a href="result-list?EDIT=true&articleID=12345"/>

Each link contains not only the event parameter SHOW or EDIT but as well
the article ID of the article to show/edit. Similar links are provided
for the other articles as well.

In contrast to the result-list page, other pages usually contain a
different set of Flow Navigation links, i.e. a different set of
transitions leading away from that page. The "choose-topic" page, for
example, just contains a Flow Navigation link to the logout page and an
option list for the topic selection:

----------------------------------------------------
| -> logout		                           |
|--------------------------------------------------|
| Choose topic:                                    |
| [ ...  v]  ->select                              |
----------------------------------------------------

As you can see, there are just 2 transitions leading away from this
page:

->logout  leads to <a href="choose-topic?LOGOUT=true"/>
->select  leads to <a href="choose-topic?SELECT=true&topicID=98"/>

Normally, you have to manage all these different links with their event
parameters and their ordinary parameters manually. They are either part
of the XML source document or part of the stylesheet. But neither of the
two locations is an optimal solution, because these links are actually
very closely related to the flow control, and this should determine the
location where they are defined.

And that's where the FlowNavigation Transformer helps: it generates
generic XML elements for all possible transitions leading away from the
current state, like <flownav:link event="LOGOUT" transition="LOGOUT"
uri="result-list"/>. With this trick we have a perfect solution
supporting a clean separation of concerns.

Now, how does this work in detail? 

Assume the following XML raw data structure (1) of the result-list page
of the above mentioned example 

<foo:page>
  <foo:environment>
    <foo:user>Paul</foo:user>
    <foo:topic>Nonsense</foo:topic>
  </foo:environment>
  <foo:articles>
    <foo:article id="12345">
       <foo:headline>Nothing important</foo:headline>
       <foo:date>01.09.2001</foo:date>
       <foo:author>MR</foo:author>
    </foo:article>
    <foo:article id="99999">
       <foo:headline>More nonsense today</foo:headline>
       <foo:date>05.09.2001</foo:date>
       <foo:author>JH</foo:author>
    </foo:article>
    <foo:article id="87654">
       <foo:headline>Even more gaga!</foo:headline>
       <foo:date>12.09.2001</foo:date>
       <foo:author>DG</foo:author>
    </foo:article>
  </foo:articles>
</foo:page>

and a TransitionMap (2) containing these transition snippets (careful:
this is NOT a complete set of transitions and states!):

<states>
  <state name="choose-topic" resource="*/choose-topic">
    <if event="LOGOUT" transition="LOGOUT"/>
    <if event="SELECT" transition="SELECTTOPIC"/>
  </state>
  <state name="search-articles" resource="*/search-articles">
    <if event="LOGOUT" transition="LOGOUT"/>
    <if event="CHOOSETOPIC" transition="NEWTOPIC"/>
    <if event="NEWSEARCH" transition="NEWSEARCH"/>
    <if event="FIND" transition="FINDARTICLE"/>
  </state>
  <state name="result-list" resource="*/result-list">
    <if event="LOGOUT" transition="LOGOUT"/>
    <if event="CHOOSETOPIC" transition="NEWTOPIC"/>
    <if event="NEWSEARCH" transition="NEWSEARCH"/>
    <if event="SHOW" transition="SHOW"/>
    <if event="EDIT" transition="EDIT"/>
  </state>
  <state name="perform-logout">
    <act type="LoginAction"/>
    <if event="OK” transition="LOGOUT-OK"/>
    <if event="ERROR" transition="LOGOUT-NOT-OK"/>
  </state>
  <state name="new-topic">
    <act type="NewTopicAction"/>
    <if event="OK" transition="NEWTOPIC-OK"/>
    <if event="ERROR" transition="NEWTOPIC-NOT-OK"/>
  </state>
  <state name="clear-searchform">
    <act type="ClearForm"/>
    <if event="OK" transition="search-articles"/>
  </state>
   ...
</states>
<transitions>
  <transition name="LOGOUT" target-state="perform-logout">
    <parameters base-xpath="/foo:page"/>
  </transition>
  <transition name="NEWTOPIC" target-state="new-topic">
    <parameters base-xpath="/foo:page"/>
  </transition>
  <transition name="NEWSEARCH" target-state="clear-search">
    <parameters base-xpath="/foo:page"/>
  </transition>
  <transition name="SHOW" target-state="show-article">
    <parameters base-xpath="/foo:page/foo:articles/foo:article">
      <parameter name="articleID" 
        xpath="/foo:page/foo:articles/foo:article/@id"/>
    </parameters>
  </transition>
  <transition name="EDIT" target-state="edit-article">
    <parameters base-xpath="/foo:page/foo:articles/foo:article">
       <parameter name="articleID"
         xpath="/foo:page/foo:articles/foo:article/@id"/>
    </parameters>
  </transition>
   ...
</transitions>

For automatic Flow Navigation generation the first step is to evaluate
the possible transitions leading away from the current state. For the
state "result-list" these are LOGOUT, NEWTOPIC, NEWSEARCH and the two
transitions that require additional parameters: SHOW and EDIT. Each of
these transitions carry a <parameters> child element, where the
base-xpath and the data that's coming along with the transition are
defined. 

Let's dive a little bit deeper into the parameter definitions of the
transitions which are evaluated by the FlowNavigation Transformer:

- The base-xpath parameter of the Transition Map marks the position in
the XML raw data (1) where the transformer-created navigation element is
placed. 

- The xpath expression of each parameter is matched against the XML raw
data (1) structure and available values are merged into the resulting
transformer-created navigation elements. The shorthand names are used to
carry the values.

For our example, the FlowNavigation Transformation leads to an
intermediate XML data structure (3) with flow navigation elements
integrated into the data: 

<foo:page>
  <flownav:link event="LOGOUT" transition="LOGOUT" uri="result-list"/>
  <flownav:link event="CHOOSETOPIC" transition="NEWTOPIC" 
     uri="result-list"/>
  <flownav:link event="NEWSEARCH" transition="NEWSEARCH" 
     uri="result-list"/>
  <foo:environment>
    <foo:user>Paul</foo:user>
    <foo:topic>Nonsense</foo:topic>
  </foo:environment>
  <foo:articles>
    <foo:article id="12345">
      <flownav:link event="SHOW" transition="SHOW" uri="result-list">
        <parameter name="articleID" 
          xpath="/foo:page/foo:articles/foo:article/@foo:id" 
          value="12345"/>
      </flownav>
      <flownav:link event="EDIT" transition="EDIT" uri="result-list">
        <parameter name="articleID" 
          xpath="/foo:page/foo:articles/foo:article/@foo:id" 
          value="12345"/>
      </flownav>
      <foo:headline>Nothing important</foo:headline>
      <foo:date>01.09.2001</foo:date>
      <foo:author>MR</foo:author>
    </foo:article>
    <foo:article id="99999">
      <flownav:link event="SHOW" transition="SHOW" uri="result-list">
        <parameter name="articleID" 
          xpath="/foo:page/foo:articles/foo:article/@foo:id"
          value="99999"/>
      </flownav>
      <flownav:link event="EDIT" transition="EDIT" uri="result-list">
        <parameter name="articleID" 
          xpath="/foo:page/foo:articles/foo:article/@foo:id"
          value="99999"/>
      </flownav>
      <foo:headline>More nonsense today</foo:headline>
      <foo:date>05.09.2001</foo:date>
      <foo:author>JH</foo:author>
    </foo:article>
    <foo:article>
	...
    </foo:article>
  </foo:articles>
</foo:page>

As you can see, the <flownav:link> elements can apply to any desired XML
data (1) element, 

- either to the page's root element itself, resulting in a "once per 
  page" occurrence of the Flow Navigation link

- or to any specific subelement of the XML data, resulting in multiple 
  occurrences of the FlowNavigation generic link element with different 
  parameter values.

The rest is pretty simple:

We just need a stylesheet that transforms the generic <flownav:...> link
elements of the intermediate XML data (3)  into navigation links (e.g.
<a href...> expressions in HTML) for the final page (4):

<a href="result-list?BYE=true">LOGOUT</a>
<a href="result-list?CHOOSETOPIC=true">NEWTOPIC</a>
<a href="result-list?NEWSEARCH=true">NEWSEARCH</a>

and

<a href="result-list?SHOW=true&articleID=12345">SHOW</a>
<a href="result-list?EDIT=true&articleID=12345">EDIT</a>
<a href="result-list?SHOW=true&articleID=99999">SHOW</a>
<a href="result-list?EDIT=true&articleID=99999">EDIT</a>
<a href="result-list?SHOW=true&articleID=...">...
<a href="result-list?EDIT=true&articleID=...">...

Of course, there are still some points that need further reflection:
(I'm sure, you can even think of more.) :-)

(1) Currently, the transition name (like LOGOUT, EDIT) is used for the
display text of the link. This very basic behaviour must certainly be
extended in order to support arbitrary or even localized link texts.

(2) For transitions leading directly to a visible state, it might be a
good idea to point to the target resource in the Flow Navigation link
instead of the current resource itself. E.g. if the SHOW transition
leads to a visible state show-article, mapped to a resouce
"show-artice", the resulting link would be 
<a href="show-article?SHOW=true&articleID=99999">SHOW</a>
 instead of the formerly proposed 
<a href="result-list?SHOW=true&articleID=99999">SHOW</a>. 
This policy could save unnecessary redirects.

That's all for today, thanks for reading. :-)

Bye,
Dani

---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org