diff -r 000000000000 -r dfb7c4ff071f commsfwtools/commstools/svg/sequence.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commsfwtools/commstools/svg/sequence.pl Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,438 @@ +# Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "Eclipse Public License v1.0" +# which accompanies this distribution, and is available +# at the URL "http://www.eclipse.org/legal/epl-v10.html". +# +# Initial Contributors: +# Nokia Corporation - initial contribution. +# +# Contributors: +# +# Description: +# + +use strict; + +# +# constants +# +my $incrementY = 20; +my $leftMargin = 60; +my $rightMargin = 150; +my $topMargin = 20; +my $topOffset = $topMargin; # is this right Nadeem? +my $objectSpacing = 110; +my $arrowWidth = 10; +my $textArrowSpacing = 1; +my $messageSpacingAboveLine = 1; +my $objectVerticalLineSpacing = 2; +my $objectUnderlineToLifelineGap = 2; + +my $objectName = 0; +my $objectX = 1; +my $objectY = 2; +my $objectMsgCount = 3; +my $objectCreationPointKnown = 4; + +my $sequenceAction = 0; +my $sequenceObjRef = 1; # if action == "t" || "oc" +my $sequenceMsgRef = 1; # if action != "t" +my $sequenceX = 2; +my $sequenceY = 3; + +my $trimSilentFlag = 0; +my $objectsDisplayedAtCreationPoint = 1; +# +# global variables +# +my $currentY = $topMargin; + +my @sequences = (); +my @objects = (); +my @messages = (); + + + +# +# Data Structures: +# +# "objects" is array of arrays: +# [ ] +# +# "sequences" is an array of arrays: +# [ "t" \objects[] "text" ] +# [ "[p|r]" \messages[n] \objects[], \objects[] ] +# [ "oc" \objects[] ] + + +# Input file format: +# +# ... +# +# specifically: +# +# [P|R] +# T +# OC +# +# actions: +# +# P Post +# R Receive +# T Text +# OC Object Create +# +# All fields are space separated text. For example: +# +# P StartFlow SCPR Flow +# + +while (<>) { + die unless s/^(\w+)\s+//; + my $action = $1; + if ($action eq "t") + { + # Text + # t + my $pos; + if (s/^(\w+)\s+//) { $pos = $1; } + my $objRef = addObject($pos); + chomp; + my $text = $_; + push @sequences, [$action, $objRef, $text]; + } + elsif ($action eq "oc") + { + # Object Create + # oc + my $objName; + if (s/^(\w+)\s+//) { $objName = $1; } + my $objRef = addObject($objName); + ${$objRef}->[$objectCreationPointKnown] = 1; + chomp; + push @sequences, [$action, $objRef]; + } + else + { + # Post/Receive + # [P|R] + split; + my $msgRef = addMessage(shift @_); + my $srcRef = addObject(shift @_); + my $destRef = addObject(shift @_); + ${$srcRef}->[$objectMsgCount]++; + ${$destRef}->[$objectMsgCount]++; + push @sequences, [$action, $msgRef, $srcRef, $destRef]; + } + } + +if ($trimSilentFlag) + { + trimSilentObjects(); + } +calculateObjectRowPositions(); + +my $screenWidth = $objects[$#objects]->[$objectX] + $rightMargin; +my $screenHeight = scalar(@sequences) * ($incrementY + 2) + $topMargin; + + +outputDocHeader($screenWidth, $screenHeight); + +drawObjectsAtTop(); + +drawObjectsRepeatedly(); + +drawSequences(); + +outputDocFooter(); + +#################### +# Message routines +#################### + +sub addMessage() + { + my $obj = $_[0]; + my $i; + for ($i = 0 ; $i < scalar(@messages) ; ++$i) { + if ($messages[$i] eq $obj) { + return \$messages[$i]; + } + } + $messages[$i] = $obj; + return \$messages[$i]; + } + +sub printMessages() + { + print "Messages (", scalar(@messages), ") : "; + foreach my $msg (@messages) { + print $msg, " "; + } + print "\n"; + } + +################### +# Object routines +################### + +sub addObject() + { + my $objName = $_[0]; + my $i; + for ($i = 0 ; $i < scalar(@objects) ; ++$i) { + if ($objects[$i]->[$objectName] eq $objName) { + return \$objects[$i]; + } + } + $objects[$i] = [ $objName, 0, 0, 0, 0 ]; + return \$objects[$i]; + } + +sub printObjects() + { + print "Objects (", scalar(@objects), "): "; + foreach my $obj (@objects) { + print $obj->[0], "(", $obj->[1], ") "; + } + print "\n"; + } + +sub calculateObjectRowPositions() + { + # first object position is at left margin + $objects[0][$objectX] = $leftMargin; + my $i; + for ($i = 1 ; $i < scalar(@objects) ; ++$i) { + $objects[$i][$objectX] = $objects[$i-1][$objectX] + $objectSpacing; + } + } + +sub trimSilentObjects() + { + # get rid of objects that didn't end up with any messages sent to/from them + my $i; + for ($i = 0 ; $i < scalar(@objects) ; ) { + if ($objects[$i][$objectMsgCount] == 0) + { + my $j; + for ($j = 0 ; $j < scalar(@sequences) ; ) + { + my $action = $sequences[$j][$sequenceAction]; + if ( (($action eq "t") || ($action eq "oc")) && + ($sequences[$j][$sequenceObjRef] == \$objects[$i]) ) + { + splice @sequences, $j, 1; +#print "delete sequence $j\n"; +#++$j; + } + else + { + ++$j; + } + } + splice @objects, $i, 1; +#print "delete object $i $objects[$i][$objectName]\n"; +#++$i; + } + else + { + ++$i; + } + } + } + +sub drawObject($$$) + { + my ($x,$y,$name) = @_; + outputText($x, $name, $y, "middle", "underline"); + outputVerticalLine($x, $y + $objectUnderlineToLifelineGap, $screenHeight - $topOffset); + } + +sub drawObjectsAtTop() + { + my $i; + foreach $i (@objects) { + if ($objectsDisplayedAtCreationPoint == 1 && $i->[$objectCreationPointKnown] == 1) + { + next; + } + outputText($i->[$objectX], $i->[$objectName], $currentY, "middle", "underline"); + } + incrementY(); + drawObjectLifelines(); + } + +sub drawObjectsRepeatedly() + { + my $i; + foreach $i (@objects) + { + for( my $j = 400 ; $j < $screenHeight ; $j += 400 ) + { + outputText($i->[$objectX], $i->[$objectName], $j, "middle", "","silver"); + } + } + } + +sub drawSequences() + { + foreach my $ref (@sequences) { + my $action = $ref->[$sequenceAction]; + if ($action eq "t") + { + my $objX = ${$ref->[$sequenceObjRef]}->[$objectX]; + my $text = $ref->[2]; + outputText($objX, $text, $currentY, "middle"); + incrementY(); + } + elsif ($action eq "oc") + { + if ($objectsDisplayedAtCreationPoint == 1) + { + my $objX = ${$ref->[$sequenceObjRef]}->[$objectX]; + my $objName = ${$ref->[$sequenceObjRef]}->[$objectName]; + drawObject($objX, $currentY, $objName); + incrementY(); + } + } + else + { + my $msg = ${$ref->[$sequenceObjRef]}; + my $srcX = ${$ref->[$sequenceX]}->[$objectX]; + my $destX = ${$ref->[$sequenceY]}->[$objectX]; + my $align; + if ($action eq "p") { + $align = "tail"; + } + elsif ($action eq "r") { + $align = "head"; + } + outputLabelledLine($srcX, $destX, $msg, $align); + incrementY(); + } + } + } + +sub drawObjectLifelines() + { + my $topOffset = $topMargin + $objectVerticalLineSpacing; + foreach my $i (@objects) { + if ($objectsDisplayedAtCreationPoint == 0 || $i->[$objectCreationPointKnown] == 0) + { + outputVerticalLine($i->[$objectX], $topOffset, $screenHeight - $topOffset); + } + } + } + +####################### +# SVG output routines +####################### + +sub outputDocHeader() + { + my ($width,$height) = @_; + print '',"\n"; + print '',"\n"; + print "\n"; + outputDefs(); + } + +sub outputDefs() + { + print "\n"; + print qq{\n}; + print qq{\t\n}; + print "\n"; + print "\n"; + } + +sub outputDocFooter() + { + print "\n"; + } + +sub outputLabelledLine() + { + my ($x1,$x2,$text,$alignment) = @_; + outputLine($x1,$x2); + my $textx; + my $anchor; + my $colour = 'grey'; + if (!$alignment || $alignment eq "mid") { + $textx = (($x1 + $x2) / 2); + $anchor = "middle"; + } + else { + if ($alignment eq "head") { + $colour='red'; + if ($x1 < $x2) { + $anchor = "end"; + $textx = $x2 - $arrowWidth - $textArrowSpacing; + } + else { + $anchor = "start"; + $textx = $x2 + $arrowWidth + $textArrowSpacing; + } + } else { # "tail" + $colour='green'; + $textx = $x1; + if ($x1 < $x2) { + $anchor = "start"; + } else { + $anchor = "end"; + } + } + } + + outputText($textx,$text,$currentY - $messageSpacingAboveLine, $anchor,'',$colour); + } + +sub outputText() + { + my ($x,$text,$y,$anchor,$decoration,$colour) = @_; + + my $attrs = qq{ x="$x" y="$y" }; + + if ($decoration) + { + $attrs .= qq{ text-decoration="$decoration" }; + } + + if ($colour) + { + $attrs .= qq{ stroke="$colour" }; + } + + if ($anchor) + { + $attrs .= qq { text-anchor="$anchor" }; + } + + print "$text\n"; + } + +sub outputLine() + { + my ($x1,$x2) = @_; + print qq{\n}; + } + +sub outputVerticalLine() + { + my ($x,$y1,$y2) = @_; + print qq{\n}; + } + +sub incrementY() + { + my $amount; + if ($_[0]) { + $amount = $_[0]; + } else { + $amount = 1; + } + $currentY += $incrementY * $amount; + }