XQuery/Sequence Diagrams

From Wikibooks, open books for an open world
Jump to: navigation, search

Background[edit]

Sequence Diagrams are tedious to draw, even with a diagramming tool. They are even worse to edit when the sequence changes. An alternative is to define an XML vocabulary to define the message sequencing and to use XQuery to render this description as XHTML. This textual approach also allows explanations to be revealed at each step and alternative renderings of the XML definition of the Sequence to be generated, such as a printed version.

This demonstrator uses a simplified meta-model, with only messages between actors and actions undertaken by actors.

(article under re-design - CW)

Models[edit]

3-tier architecture[edit]

Here is a sample description of interaction in a 3-tier architecture: (badly needs re-writing)

<SequenceDiagram id="3tier">
    <name>3-tier architecture</name>
    <description>An overview of the 3-tier Architecture</description>
    <cast>
        <actor>
            <name>user</name>
            <label>The User</label>
            <color>pink</color>
            <location>client</location>
            <description>The user of the site</description>
        </actor>
        <actor>
            <name>browser</name>
            <label>Presentation Layer</label>
            <color>lightgreen</color>
            <location>client</location>
            <description>A browser such as Firefox, Opera or Internet Explorer</description>
        </actor>
        <actor>
            <name>server</name>
            <label>Application Layer</label>
            <color>lightblue</color>
            <location>server</location>
            <description>Scripts in languages such as PHP or Java invoked via a web server</description>
        </actor>
        <actor>
            <name>database</name>
            <label>Persistance Layer</label>
            <color>grey</color>
            <location>server</location>
            <description>A database server such as Oracle or MySQL</description>
        </actor>
    </cast>
    <communication>
        <connection>
            <actor>user</actor>
            <actor>browser</actor>
            <method/>
            <prep>on</prep>
        </connection>
        <connection>
            <actor>browser</actor>
            <actor>server</actor>
            <method>HTTP</method>
            <prep>to</prep>
        </connection>
        <connection>
            <actor>server</actor>
            <actor>database</actor>
            <method>SQL</method>
            <prep>to</prep>
        </connection>
    </communication>
    <trace>
        <message>
            <from>user</from>
            <to>browser</to>
            <action>click</action>
            <object>link</object>
        </message>
        <message>
            <from>browser</from>
            <to>server</to>
            <action>request</action>
            <object>URL</object>
            <url>http://www.cems.uwe.ac.uk/~cjwallac/apps/poll2/tally.php?pollid=2</url>
        </message>
        <do>
            <at>server</at>
            <action>decode input</action>
            <object/>
        </do>
        <do>
            <at>server</at>
            <action>create SQL request</action>
            <object/>
        </do>
        <message>
            <from>server</from>
            <to>database</to>
            <action>request</action>
            <object>SQL statement</object>
        </message>
        <message>
            <from>database</from>
            <to>server</to>
            <action>respond</action>
            <object>tables</object>
        </message>
        <do>
            <at>server</at>
            <action>create page with data in table</action>
            <object/>
        </do>
        <message>
            <from>server</from>
            <to>browser</to>
            <action>respond</action>
            <object>HTML page</object>
        </message>
        <message>
            <from>user</from>
            <to>browser</to>
            <action>read</action>
            <object>page</object>
        </message>
    </trace>
</SequenceDiagram>

Rendering the diagram[edit]

The script 'displayDiagram' renders this model as an XHTML table:


declare option exist:serialize  "method=xhtml media-type=text/html indent=yes";
declare variable $homesym :=' || ';
declare variable $leftsym := ' >> ';
declare variable $rightsym := ' << ';

declare function local:makeText($event){
  concat($event/action,' ',string-join($event/object,' + '))
};


let $id:= request:get-parameter('id','')
let $sd :=//SequenceDiagram[@id=$id] 
let $trace := $sd/trace

let $actors := $sd/cast/actor
let $nactors := count($sd/cast/actor)
let $width := 100  div $nactors
return 
<html>
<head><title>Sequence Diagram {string($sd/@id)}</title>
</head>
<body>
   <h1>{string($sd/name)}  </h1>
         <div class="description">
          {$sd/description/node() }
        </div>

    <table border='1'>
             <tr>
                  {for $a in $actors 
                   return 
                        <th width='{$width}%'  bgcolor='{$a/color}'>{string($a/label)}</th>
                  }
              </tr>
              { if ($actors/description)
                then
                     <tr>
                       {for $a in $actors 
                        return <th width='{$width}%'  bgcolor='{$a/color}'>{string($a/description)} </th>
                        }
                     </tr>
                else ()
              }
              {for $event in $trace/*
               return
                     <tr>
                       {if (name($event)='do')
                        then 
                              let $p := index-of($actors/name,$event/at )
                              let $text:= local:makeText($event)
                              return
                              (  for $i in (1 to $p - 1) return <td/>,
                                  <td align='center'  bgcolor='{$actors[name=$event/at]/color}'>
                                            {
                                            if ($event/url)
                                            then <a href='{$event/url}'  target='demo'>{$text}</a>
                                            else $text
                                            }
                               </td>,
                               for $i in ($p + 1to $nactors)
                               return <td/>
                              )
                         else if (name($event)='message')
                         then 
                             let $pfrom := index-of($actors/name,$event/from )
                             let $pto := index-of($actors/name,$event/to)
                             let $pfirst := min (($pfrom,$pto))
                             let $plast := max(($pfrom,$pto))
                             let $ltor := $pfrom = $pfirst
                             let $text:= local:makeText($event)
                             let $connection := $sd//connection[actor = $event/from and actor= $event/to]
        
                              let $text := if ($ltor) 
                                                 then concat($connection/method,$leftsym,$text,$leftsym) 
                                                 else concat($rightsym,$text,$rightsym, $connection/method) 
                             return
                                 (  
                                    for $i in (1 to $pfirst - 1) 
                                    return <td/>,
                                     <td  align='center' colspan='{$plast - $pfirst + 1 }' bgcolor ='{$actors[name=$event/from]/color}' >              
                                        {$text}
                                        { if ($event/url)
                                           then <a href='{$event/url}' target='demo'>Link </a>
                                           else ()
                                        }
                                    </td>,
                                        for $i in ($plast + 1 to $nactors)
                                      return <td/>
                                  )
                     else ()
               }
       </tr>
      }             
      </table>
    </body>
</html>

Display

Further example Diagrams[edit]

  1. A GoogleEarth application

Model Display

Animating the Diagram[edit]

Rather than display the complete interaction, the diagram can be simply animated by displaying only the first n steps, together with explanatory text for the last step. The addition of some controls allows the user to step forward and backward in the sequence.

3 Tier GoogleEarth A function to compute the next step:

declare function local:next-step($step,$action, $max) {
    if  ($action = "start") 
    then 0
    else if ($action = "back")
    then max (($step -1,0))
    else if ($action = "forward")
    then min(($max,$step+1))
    else if ($action="end")
    then $max
    else $step
};

and call the function

let $step :=  local:next-step(
                               number(request:request-parameter("step",0)),
                               request:request-parameter("action", "start"),
                               count($trace/*))

A form to provide the controls and maintain the interaction state:

  <h2>
       <form>
                 <input type="hidden" name="id" value="{$id}"/>
                 <input type="hidden" name="step" value="{$step}"/>
                 <input type="submit" name="action" value="start"/>
                 <input type="submit" name="action" value="back"/>
                 <input type="submit" name="action" value="forward"/>
                 <input type="submit" name="action" value="end"/>               
         </form>
    </h2>

Limit the events displayed to the specified number of steps:

for $event in $trace/*[position()<=$step]

and display the explanation of the last step:

    <div class="description">
          {if ($step=0)
          then $sd/description/node()
          else $trace/*[position()=$step]/description/node()
          }
   </div>

Print the diagram[edit]

One of the advantages of having the whole diagram in XML is that the diagram can be displayed differently in print, so that each step can be shown with its description.

Fully expanded Descriptions