%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Start of tikz-uml.sty
%
% Some macros for UML Diagrams.
% Home page of project : 
% Author: Nicolas Kielbasiewicz
% Style from : 
% Fixed by Nicolas Kielbasiewicz (nicolas.kielbasiewicz@ensta-paristech.fr) in dec 2010 to compile with pgf 2.00
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\NeedsTeXFormat{LaTeX2e}[1995/12/01]%
\ProvidesPackage{tikz-uml}[2011/01/26]%

\RequirePackage{ifthen}%
\RequirePackage{tikz}%
\RequirePackage{xstring}%
\RequirePackage{calc}%
\RequirePackage{pgfopts}%
\usetikzlibrary{backgrounds,arrows,shapes,fit,shadows,decorations.markings}%

\def\tikzumlPackageLayersNum{3}%
\pgfkeys{/tikzuml/options/.cd, packageLayers/.initial=3}%
\pgfkeys{/tikzuml/options/.cd, packageLayers/.store in=\tikzumlPackageLayersNum}%
\def\tikzumlStateLayersNum{3}%
\pgfkeys{/tikzuml/options/.cd, stateLayers/.initial=3}%
\pgfkeys{/tikzuml/options/.cd, stateLayers/.store in=\tikzumlStateLayersNum}%
\def\tikzumlFragmentLayersNum{3}%
\pgfkeys{/tikzuml/options/.cd, fragmentLayers/.initial=3}%
\pgfkeys{/tikzuml/options/.cd, fragmentLayers/.store in=\tikzumlFragmentLayersNum}%
\def\tikzumlComponentLayersNum{3}%
\pgfkeys{/tikzuml/options/.cd, componentLayers/.initial=3}%
\pgfkeys{/tikzuml/options/.cd, componentLayers/.store in=\tikzumlComponentLayersNum}%

\ProcessPgfOptions{/tikzuml/options}%

\def\pgfsetlayersArg{background}%
\pgfdeclarelayer{background}%
\newcounter{tikzumlPackageLayers}%
\loop \pgfdeclarelayer{package\thetikzumlPackageLayers}%
  \xdef\pgfsetlayersArg{\pgfsetlayersArg,package\thetikzumlPackageLayers}%
  \ifnum\tikzumlPackageLayersNum>\thetikzumlPackageLayers%
    \stepcounter{tikzumlPackageLayers}%
\repeat%
%
\newcounter{tikzumlFragmentLayers}%
\loop \pgfdeclarelayer{fragment\thetikzumlFragmentLayers}%
  \xdef\pgfsetlayersArg{\pgfsetlayersArg,fragment\thetikzumlFragmentLayers}%
  \ifnum\tikzumlFragmentLayersNum>\thetikzumlFragmentLayers%
    \stepcounter{tikzumlFragmentLayers}%
\repeat%
%
\newcounter{tikzumlStateLayers}%
\loop \pgfdeclarelayer{state\thetikzumlStateLayers}%
  \xdef\pgfsetlayersArg{\pgfsetlayersArg,state\thetikzumlStateLayers}%
  \ifnum\tikzumlStateLayersNum>\thetikzumlStateLayers%
    \stepcounter{tikzumlStateLayers}%
\repeat%
%
\newcounter{tikzumlComponentLayers}%
\loop \pgfdeclarelayer{component\thetikzumlComponentLayers}%
  \xdef\pgfsetlayersArg{\pgfsetlayersArg,component\thetikzumlComponentLayers}%
  \ifnum\tikzumlComponentLayersNum>\thetikzumlComponentLayers%
    \stepcounter{tikzumlComponentLayers}%
\repeat%
%
\pgfdeclarelayer{lifelines}%
\pgfdeclarelayer{activity}%
\pgfdeclarelayer{connections}%
\xdef\pgfsetlayersArg{\pgfsetlayersArg,lifelines,activity,connections,main}%
\pgfsetlayers{\pgfsetlayersArg}%

\pgfkeys{/tikzuml/.cd,%
         text/.initial=black, draw/.initial=black, font/.initial=\small,%
         fill class/.initial=yellow!20, fill template/.initial=yellow!2,%
         fill package/.initial=blue!20, fill note/.initial=green!20,%
         fill usecase/.initial=blue!20, fill system/.initial=white,%
         fill state/.initial=yellow!20, fill object/.initial=yellow!20,%
         fill call/.initial=white, fill fragment/.initial= none,%
         fill component/.initial= yellow!20, fill port/.initial= yellow!20,%
         fill assembly connector/.initial= white,%
         .unknown/.code={%
           \let\keyname=\pgfkeyscurrentname%
           \errmessage{TIKZUML ERROR : in tikzuml global, invalid option \keyname}%
         }}%
\pgfkeys{/tikzuml/.cd,%
         text/.get=\tikzumltextcolor, draw/.get=\tikzumldrawcolor, font/.get=\tikzumlfont,%
         fill class/.get=\tikzumlfillclasscolor,%
         fill template/.get=\tikzumlfilltemplatecolor,%
         fill package/.get=\tikzumlfillpackagecolor, fill note/.get=\tikzumlfillnotecolor,%
         fill usecase/.get=\tikzumlfillusecasecolor,%
         fill system/.get=\tikzumlfillsystemcolor,%
         fill state/.get=\tikzumlfillstatecolor, fill object/.get=\tikzumlfillobjectcolor,%
         fill call/.get=\tikzumlfillcallcolor,%
         fill fragment/.get=\tikzumlfillfragmentcolor,%
         fill component/.get=\tikzumlfillcomponentcolor,%
         fill port/.get=\tikzumlfillportcolor,%
         fill assembly connector/.get=\tikzumlfillassemblyconnectorcolor}%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                       class diagrams                    %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\pgfkeys{/tikzuml/relation/.cd,%
         attr1/.style args={#1|#2}{arg1=#1, mult1=#2},%
         attr2/.style args={#1|#2}{arg2=#1, mult2=#2},%
         attr/.style args={#1|#2}{arg=#1, mult=#2},%
         recursive/.style args={#1|#2|#3}{angle1=#1, angle2=#2, loopsize=#3},%
         anchors/.style args={#1 and #2}{anchor1=#1, anchor2=#2},%
         recursive direction/.style args={#1 to #2}{recursive direction start=#1, recursive direction end=#2}}%
\pgfkeys{/tikzuml/note/.cd,%
         anchors/.style args={#1 and #2}{anchor1=#1, anchor2=#2}}%

\tikzstyle{tikzuml simpleclass style}=[rectangle, minimum height=2em, node distance=2em]%
\tikzstyle{tikzuml class style}=[rectangle split, rectangle split parts=3, rectangle split part align={center, left, left}, minimum height=2em, node distance=2em]%
\tikzstyle{tikzuml narynode style}=[diamond]%
\tikzstyle{tikzuml template style}=[dashed, inner ysep=0.5em, inner xsep=1ex]%
\tikzstyle{tikzuml control nodes style}=[fill=black, inner sep=1.5pt, circle]%
%
\tikzstyle{tikzuml association style}=[color=\tikzumldrawcolor, -]%
\tikzstyle{tikzuml bidirectional association style}=[color=\tikzumldrawcolor, angle45-angle45]%
\tikzstyle{tikzuml unidirectional association style}=[color=\tikzumldrawcolor, -angle 45]%
\tikzstyle{tikzuml aggregation style}=[color=\tikzumldrawcolor, open diamond-]%
\tikzstyle{tikzuml unidirectional aggregation style}=[color=\tikzumldrawcolor, open diamond-angle 45]%
\tikzstyle{tikzuml composition style}=[color=\tikzumldrawcolor, diamond-]%
\tikzstyle{tikzuml unidirectional composition style}=[color=\tikzumldrawcolor, diamond-angle 45]%
\tikzstyle{tikzuml dependency style}=[color=\tikzumldrawcolor, -angle 45, dashed]%
\tikzstyle{tikzuml import style}=[color=\tikzumldrawcolor, -angle 45, dashed]%
\tikzstyle{tikzuml inherit style}=[color=\tikzumldrawcolor, -open triangle 45]%
\tikzstyle{tikzuml implements style}=[color=\tikzumldrawcolor, -open triangle 45, dashed]%

\pgfkeys{/tikzuml/assemblyconnectorrelation/.cd, anchors/.style args={#1 and #2}{anchor1=#1, anchor2=#2}}%

\newcounter{tikzumlPackageClassNum}%
\newcounter{tikzumlPackageSubPackageNum}%
\newcounter{tikzumlRelationNum}%
\setcounter{tikzumlRelationNum}{1}%
\newcounter{tikzumlNoteNum}%
\setcounter{tikzumlNoteNum}{1}%

\newcounter{pos}%
\newcounter{posT}%
\newcounter{posStereo}%

\newcounter{tikzumlPackageLevel}%
\setcounter{tikzumlPackageLevel}{0}%

\newif\ifumlclassSimpleStyle%

% utility : change default colors
\newcommand{\tikzumlset}[1]{%
  \pgfkeys{/tikzuml/.cd,#1}%
  \pgfkeys{/tikzuml/.cd,%
           text/.get=\tikzumltextcolor, draw/.get=\tikzumldrawcolor,%
           font/.get=\tikzumlfont,%
           fill class/.get=\tikzumlfillclasscolor,%
           fill template/.get=\tikzumlfilltemplatecolor,%
           fill package/.get=\tikzumlfillpackagecolor,%
           fill note/.get=\tikzumlfillnotecolor,%
           fill usecase/.get=\tikzumlfillusecasecolor,%
           fill system/.get=\tikzumlfillsystemcolor,%
           fill state/.get=\tikzumlfillstatecolor,%
           fill object/.get=\tikzumlfillobjectcolor,%
           fill call/.get=\tikzumlfillcallcolor,%
           fill fragment/.get=\tikzumlfillfragmentcolor,%
           fill component/.get=\tikzumlfillcomponentcolor,%
           fill port/.get=\tikzumlfillportcolor,%
           fill assembly connector/.get=\tikzumlfillassemblyconnectorcolor}%
}%

% define a point
% arg : node/coordinates of the point
\newcommand{\umlpoint}[1]{%
  \begin{pgfonlayer}{connections}%
  \node[tikzuml control nodes style] at (#1) {};%
  \end{pgfonlayer}%
}%

\newcommand{\tikzumlskipescape}[3][_]{%
\begingroup%
  \def\_{#1}\edef\x{\endgroup%
    \def\noexpand\csname #3\endcsname{#2}}\x%
}%

% define a uml package
%  arg : package name
%  optional : x, y coordinates of the package
%             draw, fill, text colors
\newenvironment{umlpackage}[2][]{%
  \pgfkeys{/tikzuml/package/.cd,%
           x/.initial=0, y/.initial=0,%
           name/.initial=tikzumlEmpty, draw/.initial=\tikzumldrawcolor,% 
           fill/.initial=\tikzumlfillpackagecolor, text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlpackage, invalid option \keyname}%
                                }}%
  \pgfkeys{/tikzuml/package/.cd, #1}%
  \pgfkeys{/tikzuml/package/.cd,%
           x/.get=\xshift, y/.get=\yshift, name/.get=\tikzumlpackagename,%
           draw/.get=\tikzumlpackagedraw, fill/.get=\tikzumlpackagefill,%
           text/.get=\tikzumlpackagetext}%
  %
  \ifnum\thetikzumlPackageLevel>0%
    \let\tikzumlPackage@nameold\tikzumlPackage@fitname%
    \def\tikzumlPackage@name{#2}%
    \begingroup%
      \def\_{@}\edef\x{\endgroup%
        \def\noexpand\tikzumlPackage@fitname{\tikzumlPackage@name}}\x%
    \let\tikzumlPackage@parentold\tikzumlPackage@parent%
    \edef\tikzumlPackage@parent{\tikzumlPackage@parentold @@\tikzumlPackage@nameold}%
  \else%
    \def\tikzumlPackage@parent{}%
    \def\tikzumlPackage@name{#2}%
    \begingroup%
      \def\_{@}\edef\x{\endgroup%
        \def\noexpand\tikzumlPackage@fitname{\tikzumlPackage@name}}\x%
  \fi%
  %
  \let\tikzumlPackage@nodeNameold\tikzumlPackage@nodeName%
  %  
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlPackage@nodeName{\tikzumlPackage@name}}\x%
  %
  \ifthenelse{\equal{\tikzumlpackagename}{tikzumlEmpty}}{}{%
    \def\tikzumlPackage@nodeName{\tikzumlpackagename}%
  }%
  %
  \StrSubstitute{\tikzumlPackage@nodeName}{.}{@POINT@}{\tikzumlPackage@nodeName}%
  %
  \expandafter\gdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{}%
  %
  \setcounter{tikzumlPackageClassNum}{0}%
  \setcounter{tikzumlPackageSubPackageNum}{0}%
  \stepcounter{tikzumlPackageLevel}%
  %
  \begin{scope}[xshift=\xshift cm, yshift=\yshift cm]%
}{%
  \addtocounter{tikzumlPackageLevel}{-1}%
  \begin{pgfonlayer}{package\thetikzumlPackageLevel}%
  %
  % if contains no class, one define a fictive node to enable the fit option
  \ifnum\c@tikzumlPackageClassNum=0%
    \ifnum\c@tikzumlPackageSubPackageNum=0%
      \node[inner sep=1.5ex] (\tikzumlPackage@nodeName-root) at (0,0) {\phantom{\tikzumlPackage@nodeName}};%
      \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{(\tikzumlPackage@nodeName-root)}%
      %
    \fi%
  \fi%
  %
  \ifnum\c@tikzumlPackageLevel>0%
    \def\tikzumlPackageFitTmp{\csname tikzumlPackageFit\tikzumlPackage@parent\endcsname}%
    \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent\endcsname{\tikzumlPackageFitTmp (\tikzumlPackage@nodeName) (\tikzumlPackage@nodeName-caption)}%
    \stepcounter{tikzumlPackageSubPackageNum}%
  \fi%
  %
  \node[draw=\tikzumlpackagedraw, fill=\tikzumlpackagefill, text=\tikzumlpackagetext, font=\tikzumlfont, inner sep=1.5ex, fit = \csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname] (\tikzumlPackage@nodeName) {};%
  \node[draw=\tikzumlpackagedraw, fill=\tikzumlpackagefill, text=\tikzumlpackagetext, font=\tikzumlfont, minimum height=1.5em, outer ysep=-0.3, anchor=south west] (\tikzumlPackage@nodeName-caption) at (\tikzumlPackage@nodeName.north west) {\tikzumlPackage@name};%
  \end{pgfonlayer}%
  \end{scope}%
}%

% shortcut to define an empty package
\newcommand{\umlemptypackage}[2][]{\begin{umlpackage}[#1]{#2} \end{umlpackage}}%

% define a uml class
% args : name of the class
%        attributes of the class
%        operations of the class
% optional : x,y coordinates of the class
%            width of the class node
%            type of class (class, interface, typedef, enum)
%            template parameters
%            draw, fill, text colors
\newcommand{\umlclass}[4][]{%
  \pgfkeys{/tikzuml/class/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=10ex, type/.initial=class,%
           tags/.initial={}, simple/.is if=umlclassSimpleStyle,%
           template/.initial={}, name/.initial={tikzumlEmpty},%
           draw/.initial=\tikzumldrawcolor,%
           fill template/.initial=\tikzumlfilltemplatecolor,%
           fill/.initial=\tikzumlfillclasscolor,%
           text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlclass, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/class/.cd,#1}%
  \pgfkeys{/tikzuml/class/.cd,%
           x/.get=\umlclassX, y/.get=\umlclassY, width/.get=\umlclassMinimumWidth,% 
           type/.get=\umlclassType, tags/.get=\umlclasstags, template/.get=\umlclassTemplateParam,%
           name/.get=\umlclassName,%
           draw/.get=\tikzumlclassdraw, fill/.get=\tikzumlclassfill,%
           text/.get=\tikzumlclasstext, fill template/.get=\tikzumlclasstemplate}%
  %
  \ifthenelse{\equal{\umlclassType}{class}\OR\equal{\umlclassType}{abstract}}{%
    \def\tikzumlClassType{}%
  }{%
    \def\tikzumlClassType{\guillemotleft\umlclassType\guillemotright \\}%
  }%
  %
  \ifthenelse{\equal{\umlclasstags}{}}{%
    \def\tikzumlClassTags{}%
  }{%
    \def\tikzumlClassTags{\\ \{\umlclasstags\}}%
  }%
  %
  \ifthenelse{\equal{\umlclassTemplateParam}{}}{%
    \def\tikzumlClassVPadding{}%
    \def\tikzumlClassHPadding{}%
  }{%
    \def\tikzumlClassVPadding{\vspace{0.1em} \\}%
    \def\tikzumlClassHPadding{\hspace{0.5ex} $ $}%
  }%
  %
  \def\tikzumlClassName{#2}%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlClassNodeName{\tikzumlClassName}}\x%
  %
  \ifthenelse{\equal{\umlclassName}{tikzumlEmpty}}{}{%
    \def\tikzumlClassNodeName{\umlclassName}%
  }%
  %
  \StrSubstitute{\tikzumlClassNodeName}{:}{@COLON@}[\tikzumlClassNodeName]
  %
  \ifthenelse{\equal{\umlclassType}{abstract}}{%
    \let\tikzumlClassNameOld\tikzumlClassName%
    \def\tikzumlClassName{{\it \tikzumlClassNameOld}}%
  }{}%
  %
  \def\tikzumlClassPos{\umlclassX,\umlclassY}%
  \def\tikzumlClassAttributes{#3}%
  \def\tikzumlClassOperations{#4}%
  %
  \ifumlclassSimpleStyle%
    \node[tikzuml simpleclass style, draw=\tikzumlclassdraw, fill=\tikzumlclassfill, text=\tikzumlclasstext, font=\tikzumlfont, minimum width=\umlclassMinimumWidth] (\tikzumlClassNodeName) at (\tikzumlClassPos) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}%
    };%
  \else%
    \node[tikzuml class style, draw=\tikzumlclassdraw, fill=\tikzumlclassfill, text=\tikzumlclasstext, font=\tikzumlfont, minimum width=\umlclassMinimumWidth] (\tikzumlClassNodeName) at (\tikzumlClassPos) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}%
    \nodepart{second}%
    \begin{tabular}{l}%
    \tikzumlClassAttributes%
    \end{tabular}%
    \nodepart{third}%
    \begin{tabular}{l}%
    \tikzumlClassOperations%
    \end{tabular}%
    };%
  \fi%
  %
  \ifthenelse{\equal{\umlclassTemplateParam}{}}{}{%
    \draw (\tikzumlClassNodeName.north east) node[tikzuml template style, name=\tikzumlClassNodeName-template, draw=\tikzumlclassdraw, fill=\tikzumlclasstemplate, text=\tikzumlclasstext, font=\tikzumlfont] {\umlclassTemplateParam};%
  }%
  %
  % add to fit
  \ifnum\c@tikzumlPackageLevel>0%
    \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}%
    \ifthenelse{\equal{\umlclassTemplateParam}{}}{%
      \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlClassNodeName)}%
    }{%
      \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlClassNodeName) (\tikzumlClassNodeName-template)}%
    }%
    \stepcounter{tikzumlPackageClassNum}%
  \fi%
  \ifnum\c@tikzumlComponentLevel>0%
    \message{class \tikzumlComponent@parent{} @@@@ \tikzumlComponent@fitname}
    \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname}%
    \ifthenelse{\equal{\umlclassTemplateParam}{}}{%
      \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlClassNodeName)}%
    }{%
      \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlClassNodeName) (\tikzumlClassNodeName-template)}%
    }%
    \stepcounter{tikzumlComponentSubComponentNum}%
  \fi%
}%

% shortcuts for interface, enum and typedef environments
\newcommand{\umlabstract}[4][]{\umlclass[type=abstract,#1]{#2}{#3}{#4}}%
\newcommand{\umlinterface}[4][]{\umlclass[type=interface,#1]{#2}{#3}{#4}}%
\newcommand{\umltypedef}[4][]{\umlclass[type=typedef,#1]{#2}{#3}{#4}}%
\newcommand{\umlenum}[4][]{\umlclass[type=enum,#1]{#2}{#3}{#4}}%

% shortcut to define an empty class
\newcommand{\umlemptyclass}[2][]{\umlclass[#1]{#2}{}{}}%
\newcommand{\umlsimpleclass}[2][]{%
  \pgfkeys{/tikzuml/friendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlCNfriend, forbidden option stereo}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
  \umlemptyclass[simple, #1]{#2}%
}%

% underline the text for static arg
\newcommand{\umlstatic}[1]{\underline{#1}}%
\newcommand{\umlvirt}[1]{\textit{#1}}%

% define node for n-ary association
\newcommand{\umlNarynode}[2][]{%
  \def\tikzumlNaryNodeAnchor{.north}
  \def\tikzumlNaryNodeLabelPos{above}
  \pgfkeys{/tikzuml/narynode/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=6ex, name/.initial={tikzumlEmpty},%
           draw/.initial=\tikzumldrawcolor,  fill/.initial=\tikzumlfillclasscolor,%
           text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{above}}{%
               \def\tikzumlNaryNodeAnchor{.north}%
               \def\tikzumlNaryNodeLabelPos{above}%
             }{%
               \ifthenelse{\equal{\keyname}{above left}}{%
                 \def\tikzumlNaryNodeAnchor{.north west}%
                 \def\tikzumlNaryNodeLabelPos{above left}%
               }{%
                 \ifthenelse{\equal{\keyname}{left}}{%
                   \def\tikzumlNaryNodeAnchor{.west}%
                   \def\tikzumlNaryNodeLabelPos{left}%
                 }{%
                   \ifthenelse{\equal{\keyname}{below left}}{%
                     \def\tikzumlNaryNodeAnchor{.south west}%
                     \def\tikzumlNaryNodeLabelPos{below left}%
                   }{%
                     \ifthenelse{\equal{\keyname}{below}}{%
                       \def\tikzumlNaryNodeAnchor{.south}%
                       \def\tikzumlNaryNodeLabelPos{below}%
                     }{%
                       \ifthenelse{\equal{\keyname}{below right}}{%
                         \def\tikzumlNaryNodeAnchor{.south east}%
                         \def\tikzumlNaryNodeLabelPos{below right}%
                       }{%
                         \ifthenelse{\equal{\keyname}{right}}{%
                           \def\tikzumlNaryNodeAnchor{.east}%
                           \def\tikzumlNaryNodeLabelPos{right}%
                         }{%
                           \ifthenelse{\equal{\keyname}{above right}}{%
                             \def\tikzumlNaryNodeAnchor{.north east}%
                             \def\tikzumlNaryNodeLabelPos{above right}%
                           }{%
                             \errmessage{TIKZUML ERROR : in umlNarynode, invalid option \keyname}%
                           }%
                         }%
                       }%
                     }%
                   }%
                 }%
               }%
             }%
           }}%
  \pgfkeys{/tikzuml/narynode/.cd,#1}%
  \pgfkeys{/tikzuml/narynode/.cd,%
           x/.get=\umlnarynodeX, y/.get=\umlnarynodeY, width/.get=\umlnarynodeMinimumWidth,%
           name/.get=\umlnaryName,%
           draw/.get=\tikzumlnarynodedraw, fill/.get=\tikzumlnarynodefill,%
           text/.get=\tikzumlnarynodetext}%
  %
  \def\tikzumlNaryName{#2}%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlNaryNodeName{\tikzumlNaryName}}\x%
  %
  \ifthenelse{\equal{\umlnaryName}{tikzumlEmpty}}{}{%
    \def\tikzumlNaryNodeName{\umlnaryName}%
  }%
  %
  \StrSubstitute{\tikzumlNaryNodeName}{:}{@COLON@}[\tikzumlNaryNodeName]
  %
  \def\tikzumlNarynodePos{\umlnarynodeX,\umlnarynodeY}%
  %
  \node[tikzuml narynode style, draw=\tikzumlnarynodedraw, fill=\tikzumlnarynodefill, text=\tikzumlnarynodetext, font=\tikzumlfont, minimum width=\umlnarynodeMinimumWidth, minimum height=\umlnarynodeMinimumWidth] (\tikzumlNaryNodeName) at (\tikzumlNarynodePos) {};%
  \draw (\tikzumlNaryNodeName\tikzumlNaryNodeAnchor) node[\tikzumlNaryNodeLabelPos] {\tikzumlNaryName};
  %
  % add to fit
  \ifnum\c@tikzumlPackageLevel>0%
    \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}%
    \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlNaryNodeName)}%
    \stepcounter{tikzumlPackageClassNum}%
  \fi%
}%

% main command to define a relation between two classes
% args : src class
%        dest class
% optional : geometry of the line
%            barycentric weight
%            name of the src class type attribute defined by the relation
%            multiplicity of the src class type attribute defined by the relation
%            position on the relation
%            text justification on the relation
%            name of the dest class type attribute defined by the relation
%            multiplicity of the dest class type attribute defined by the relation
%            position on the relation
%            anchors on linked classes
%            text justification on the relation
%            start angle, end angle and size of the relation (only if recursive)
%            stereotype of the relation
%            style of the relation (association, aggregation, composition, inherit, ...)
\newcommand{\umlrelation}[3][]{%
  \pgfkeys{/tikzuml/relation/.cd,%
           geometry/.initial=--, weight/.initial=0.5,%
           arm1/.initial={auto}, arm2/.initial={auto},%
           arg1/.initial={}, arg2/.initial={}, arg/.initial={},%
           mult1/.initial={}, mult2/.initial={}, mult/.initial={},%
           pos1/.initial=0.2, pos2/.initial=0.8, pos/.initial={tikzumlEmpty},%
           align1/.initial={}, align2/.initial={}, align/.initial={},%
           anchor1/.initial={tikzumlEmpty}, anchor2/.initial={tikzumlEmpty},%
           angle1/.initial=-30, angle2/.initial=30, loopsize/.initial=3em,%
           stereo/.initial={}, pos stereo/.initial=0.5,%
           style/.initial=->, name/.initial=relation-\thetikzumlRelationNum,%
           recursive mode/.initial=default, recursive direction start/.initial=right,%
           recursive direction end/.initial=bottom,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{with port}%
                      \OR\equal{\keyname}{interface}%
                      \OR\equal{\keyname}{padding}%
                      \OR\equal{\keyname}{width}%
                      \OR\equal{\keyname}{first arm}%
                      \OR\equal{\keyname}{second arm}%
                      \OR\equal{\keyname}{middle arm}%
                      \OR\equal{\keyname}{last arm}%
                      \OR\equal{\keyname}{distance}}{}{%
                        \errmessage{TIKZUML ERROR : in umlrelation, invalid option \keyname}%
             }%
           }}%
  \pgfkeys{/tikzuml/relation/.cd,#1}%
  \pgfkeys{/tikzuml/relation/.cd,%
           geometry/.get=\geometry, weight/.get=\weight, arm1/.get=\armO, arm2/.get=\armT,%
           arg1/.get=\attrName, arg2/.get=\attrNameTO, arg/.get=\attrNameTT,%
           mult1/.get=\multiplicity, mult2/.get=\multiplicityTO, mult/.get=\multiplicityTT,%
           pos1/.get=\position, pos2/.get=\positionTO, pos/.get=\positionTT,%
           align1/.get=\align, align2/.get=\alignTO, align/.get=\alignTT,%
           anchor1/.get=\tikzumlSrcAnchor, anchor2/.get=\tikzumlDestAnchor,%
           angle1/.get=\startangle, angle2/.get=\endangle, loopsize/.get=\loopsize,%
           stereo/.get=\stereo, pos stereo/.get=\positionStereotype,%
           style/.get=\style, name/.get=\relationName,%
           recursive mode/.get=\tikzumlrecmode,%
           recursive direction start/.get=\tikzumlrecdirstart,%
           recursive direction end/.get=\tikzumlrecdirend}%
  %
  \def\tikzumlSrcClassName{#2}%
  %
  % managing \_ in class names for node names
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlSrcClassNodeName{\tikzumlSrcClassName}}\x%
  %
  \StrSubstitute{\tikzumlSrcClassNodeName}{:}{@COLON@}[\tikzumlSrcClassNodeName]
  %
  \def\tikzumlDestClassName{#3}%
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlDestClassNodeName{\tikzumlDestClassName}}\x%
  %
  \StrSubstitute{\tikzumlDestClassNodeName}{:}{@COLON@}[\tikzumlDestClassNodeName]
  %
  % managing alias keys
  \def\attrNameT{\attrNameTO\attrNameTT}%
  \def\multiplicityT{\multiplicityTO\multiplicityTT}%
  \def\alignT{\alignTO\alignTT}%
  \def\posAttrName{}%
  \def\posMultiplicity{}%
  \def\posAttrNameT{}%
  \def\posMultiplicityT{}%
  %
  \ifthenelse{\equal{\positionTT}{tikzumlEmpty}}{%
    \def\positionT{\positionTO}%
  }{%
    \def\positionT{\positionTT}%
  }%
  %
  \def\attrAlign{}%
  \def\multAlign{}%
  \def\attrAlignT{}%
  \def\multAlignT{}%
  %
  \ifthenelse{\equal{\align}{left}}{%
    \def\attrAlign{above right}%
    \def\multAlign{below right}%
  }{%
    \ifthenelse{\equal{\align}{right}}{%
      \def\attrAlign{above left}%
      \def\multAlign{below left}%
    }{}%
  }%
  %
  \ifthenelse{\equal{\alignT}{left}}{%
    \def\attrAlignT{above right}%
    \def\multAlignT{below right}%
  }{%
    \ifthenelse{\equal{\alignT}{right}}{%
      \def\attrAlignT{above left}%
      \def\multAlignT{below left}%
    }{}%
  }%
  %
  % def stereotype
  \ifthenelse{\equal{\stereo}{}}{%
    \def\stereotype{}%
  }{%
    \def\stereotype{\guillemotleft\stereo\guillemotright}%
  }%
  
  % def anchors macros
  \ifthenelse{\equal{\tikzumlSrcAnchor}{tikzumlEmpty}}{%
    \def\tikzumlSrcAnchor{}%
  }{%
    \let\tikzumlSrcAnchorold\tikzumlSrcAnchor%
    \def\tikzumlSrcAnchor{.\tikzumlSrcAnchorold}%
  }%
  %
  \ifthenelse{\equal{\tikzumlDestAnchor}{tikzumlEmpty}}{%
    \def\tikzumlDestAnchor{}%
  }{%
    \let\tikzumlDestAnchorold\tikzumlDestAnchor%
    \def\tikzumlDestAnchor{.\tikzumlDestAnchorold}%
  }%
  %
  \setcounter{pos}{100*\real{\position}}%
  \setcounter{posT}{100*\real{\positionT}}%
  \setcounter{posStereo}{100*\real{\positionStereotype}}%
  %
  \pgfmathsetmacro{\weightT}{1-\real{\weight}}%
  %
  \def\tikzumlControlNodesNum{0}%
  %
  \def\pos{\position}%
  \def\posT{\positionT}%
  \def\posStereo{\positionStereotype}%
  %
  \node[inner sep=0] (\relationName-middle) at (barycentric cs:\tikzumlSrcClassNodeName=\weightT,\tikzumlDestClassNodeName=\weight) {};%
  %
  % straight line
  \ifthenelse{\equal{\geometry}{--}}{%
    \ifthenelse{\equal{\tikzumlSrcClassNodeName}{\tikzumlDestClassNodeName}}{%
      \def\arcNum{1}%
      \def\arcNumT{1}%
      %
      \ifthenelse{\equal{\tikzumlrecmode}{default}}{%
        \xdef\tikzumlLastArc{node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                             node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}%
                             node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                             node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}%
                             node[pos=\positionStereotype, anchor=center] {\stereotype} }%
        \xdef\tikzumlPath{(\tikzumlSrcClassNodeName) edge[in=\endangle, out=\startangle, distance=\loopsize] \tikzumlLastArc%
                                                          node[midway, inner sep=0, name=\relationName-1, anchor=center] {} (\tikzumlDestClassNodeName) }%
      }{%
        \ifthenelse{\equal{\tikzumlrecmode}{transition}}{%
          \xdef\tikzumlFirstArc{node[midway, inner sep=0, name=\relationName-1, anchor=center] {}}%
          \xdef\tikzumlMidOneArc{node[midway, inner sep=0, name=\relationName-3, anchor=center] {}}%
          %
          \ifthenelse{\equal{\tikzumlrecdirstart}{\tikzumlrecdirend}}{%
            \def\numArcs{3}%
            \xdef\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-5, anchor=center] {}}%
            %
            \begin{pgfonlayer}{connections}%
            \draw (\tikzumlSrcClassNodeName) edge[in=\endangle, out=\startangle, distance=\loopsize, draw=none] %
                                                  node[midway, inner sep=0, name=\relationName-tmp, anchor=center] {} (\tikzumlDestClassNodeName);%
            \ifthenelse{\equal{\tikzumlrecdirstart}{right}\OR\equal{\tikzumlrecdirstart}{left}}{%
              \node[inner sep=0, name=\relationName-2] at (\tikzumlSrcClassNodeName.\startangle -| \relationName-tmp) {};%
              \node[inner sep=0, name=\relationName-4] at (\tikzumlDestClassNodeName.\endangle -| \relationName-tmp) {};%
            }{%
              \node[inner sep=0, name=\relationName-2] at (\tikzumlSrcClassNodeName.\startangle |- \relationName-tmp) {};%
              \node[inner sep=0, name=\relationName-4] at (\tikzumlDestClassNodeName.\endangle |- \relationName-tmp) {};%
            }%
            \end{pgfonlayer}%
          }{%
            \def\numArcs{4}%
            \xdef\tikzumlMidTwoArc{node[midway, inner sep=0, name=\relationName-5, anchor=center] {}}%
            \xdef\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-7, anchor=center] {}}%
            %
            \begin{pgfonlayer}{connections}%
            \draw (\tikzumlSrcClassNodeName) edge[in=\endangle, out=\startangle, distance=\loopsize, draw=none] %
                                                  node[midway, name=\relationName-4, anchor=center] {} (\tikzumlDestClassNodeName);%
            \ifthenelse{\equal{\tikzumlrecdirstart}{right}\OR\equal{\tikzumlrecdirstart}{left}}{%
              \node[inner sep=0, name=\relationName-2] at (\tikzumlSrcClassNodeName.\startangle -| \relationName-4) {};%
              \node[inner sep=0, name=\relationName-6] at (\tikzumlDestClassNodeName.\endangle |- \relationName-4) {};%
            }{%
              \node[inner sep=0, name=\relationName-2] at (\tikzumlSrcClassNodeName.\startangle |- \relationName-4) {};%
              \node[inner sep=0, name=\relationName-6] at (\tikzumlDestClassNodeName.\endangle -| \relationName-4) {};%
            }%
            \end{pgfonlayer}%
          }%
          %
          \ifnum\numArcs=4%
            \ifnum\theposStereo>300%
              \pgfmathsetmacro{\posStereo}{(\theposStereo-300)/100}%
              \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype}}%
            \else%
              \ifnum\theposStereo<100%
                \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype}}%
              \else%
                \ifnum\theposStereo>200%
                  \pgfmathsetmacro{\posStereo}{(\theposStereo-200)/100}%
                  \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\posStereo, anchor=center] {\stereotype}}%
                \else%
                  \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}%
                  \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posStereo, anchor=center] {\stereotype}}%
                \fi%
              \fi%
            \fi%
            %
            \ifthenelse{\thepos=300\OR\thepos=100}{%
              \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{%
                \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{%
                  \def\posAttrName{above right}%
                  \def\posMultiplicity{below left}%
                }{%
                  \def\posAttrName{above left}%
                  \def\posMultiplicity{below right}%
                }%
              }{%
                \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{%
                  \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{%
                    \def\posAttrName{above left}%
                    \def\posMultiplicity{below right}%
                  }{%
                    \def\posAttrName{above right}%
                    \def\posMultiplicity{below left}%
                  }%
                }{%
                  \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{%
                    \ifthenelse{\equal{\tikzumlrecdirend}{left}}{%
                      \def\posAttrName{above right}%
                      \def\posMultiplicity{below left}%
                    }{%
                      \def\posAttrName{above left}%
                      \def\posMultiplicity{below right}%
                    }%
                  }{%
                    \ifthenelse{\equal{\tikzumlrecdirend}{left}}{%
                      \def\posAttrName{above left}%
                      \def\posMultiplicity{below right}%
                    }{%
                      \def\posAttrName{above right}%
                      \def\posMultiplicity{below left}%
                    }%
                  }%
                }%
              }%
            }{}%
            %
            \ifthenelse{\thepos=200}{%
              \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{%
                \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{%
                  \def\posAttrName{above left}%
                  \def\posMultiplicity{below right}%
                }{%
                  \def\posAttrName{above right}%
                  \def\posMultiplicity{below left}%
                }%
              }{%
                \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{%
                  \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{%
                    \def\posAttrName{above right}%
                    \def\posMultiplicity{below left}%
                  }{%
                    \def\posAttrName{above left}%
                    \def\posMultiplicity{below right}%
                  }%
                }{%
                  \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{%
                    \ifthenelse{\equal{\tikzumlrecdirend}{left}}{%
                      \def\posAttrName{above left}%
                      \def\posMultiplicity{below right}%
                    }{%
                      \def\posAttrName{above right}%
                      \def\posMultiplicity{below left}%
                    }%
                  }{%
                    \ifthenelse{\equal{\tikzumlrecdirend}{left}}{%
                      \def\posAttrName{above right}%
                      \def\posMultiplicity{below left}%
                    }{%
                      \def\posAttrName{above left}%
                      \def\posMultiplicity{below right}%
                    }%
                  }%
                }%
              }%
            }{}%
            %
            \ifnum\thepos>300%
              \pgfmathsetmacro{\pos}{(\thepos-300)/100}%
              \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                   node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}%
                                   }%
            \else%
              \ifnum\thepos<100%
                \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                     node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}%
                                     }%
              \else%
                \ifnum\thepos>200%
                  \pgfmathsetmacro{\pos}{(\thepos-200)/100}%
                  \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                         node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}%
                                        }%
                \else%
                  \pgfmathsetmacro{\pos}{(\thepos-100)/100}%
                  \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                         node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}%
                                        }%
                \fi%
              \fi%
            \fi%
            %
            \ifthenelse{\theposT=300\OR\theposT=100}{%
              \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{%
                \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{%
                  \def\posAttrNameT{above right}%
                  \def\posMultiplicityT{below left}%
                }{%
                  \def\posAttrNameT{above left}%
                  \def\posMultiplicityT{below right}%
                }%
              }{%
                \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{%
                  \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{%
                    \def\posAttrNameT{above left}%
                    \def\posMultiplicityT{below right}%
                  }{%
                    \def\posAttrNameT{above right}%
                    \def\posMultiplicityT{below left}%
                  }%
                }{%
                  \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{%
                    \ifthenelse{\equal{\tikzumlrecdirend}{left}}{%
                      \def\posAttrNameT{above right}%
                      \def\posMultiplicityT{below left}%
                    }{%
                      \def\posAttrNameT{above left}%
                      \def\posMultiplicityT{below right}%
                    }%
                  }{%
                    \ifthenelse{\equal{\tikzumlrecdirend}{left}}{%
                      \def\posAttrNameT{above left}%
                      \def\posMultiplicityT{below right}%
                    }{%
                      \def\posAttrNameT{above right}%
                      \def\posMultiplicityT{below left}%
                    }%
                  }%
                }%
              }%
            }{}%
            \ifthenelse{\theposT=200}{%
              \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{%
                \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{%
                  \def\posAttrNameT{above left}%
                  \def\posMultiplicity{below right}%
                }{%
                  \def\posAttrNameT{above right}%
                  \def\posMultiplicityT{below left}%
                }%
              }{%
                \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{%
                  \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{%
                    \def\posAttrNameT{above right}%
                    \def\posMultiplicityT{below left}%
                  }{%
                    \def\posAttrNameT{above left}%
                    \def\posMultiplicityT{below right}%
                  }%
                }{%
                  \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{%
                    \ifthenelse{\equal{\tikzumlrecdirend}{left}}{%
                      \def\posAttrNameT{above left}%
                      \def\posMultiplicityT{below right}%
                    }{%
                      \def\posAttrNameT{above right}%
                      \def\posMultiplicityT{below left}%
                    }%
                  }{%
                    \ifthenelse{\equal{\tikzumlrecdirend}{left}}{%
                      \def\posAttrNameT{above right}%
                      \def\posMultiplicityT{below left}%
                    }{%
                      \def\posAttrNameT{above left}%
                      \def\posMultiplicityT{below right}%
                    }%
                  }%
                }%
              }%
            }{}%
            %
            \ifnum\theposT>300%
              \pgfmathsetmacro{\posT}{(\theposT-300)/100}%
              \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                   node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}%
                                   }%
            \else%
              \ifnum\theposT<100%
                \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                     node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}%
                                     }%
              \else%
                \ifnum\theposT>200%
                  \pgfmathsetmacro{\posT}{(\theposT-200)/100}%
                  \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                         node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}%
                                        }%
                \else%
                  \pgfmathsetmacro{\posT}{(\theposT-100)/100}%
                  \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                         node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}%
                                        }%
                \fi%
              \fi%
            \fi%
          \else%
            \ifnum\theposStereo>200%
              \pgfmathsetmacro{\posStereo}{(\theposStereo-200)/100}%
              \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }%
            \else%
              \ifnum\theposStereo<100%
                \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }%
              \else%
                \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}%
                \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posStereo, anchor=center] {\stereotype} }%
              \fi%
            \fi%
            %
            \ifthenelse{\thepos=100}{%
              \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{%
                \ifthenelse{\endangle<\startangle}{%
                  \def\posAttrName{above right}%
                  \def\posMultiplicity{below left}%
                }{%
                  \def\posAttrName{above left}%
                  \def\posMultiplicity{below right}%
                }%
              }{%
                \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{%
                  \ifthenelse{\endangle<\startangle}{%
                    \def\posAttrName{above left}%
                    \def\posMultiplicity{below right}%
                  }{%
                    \def\posAttrName{above right}%
                    \def\posMultiplicity{below left}%
                  }%
                }{%
                  \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{%
                    \ifthenelse{\endangle<\startangle}{%
                      \def\posAttrName{above right}%
                      \def\posMultiplicity{below left}%
                    }{%
                      \def\posAttrName{above left}%
                      \def\posMultiplicity{below right}%
                    }%
                  }{%
                    \ifthenelse{\endangle<\startangle}{%
                      \def\posAttrName{above left}%
                      \def\posMultiplicity{below right}%
                    }{%
                      \def\posAttrName{above right}%
                      \def\posMultiplicity{below left}%
                    }%
                  }%
                }%
              }%
            }{}%
            %
            \ifthenelse{\thepos=200}{%
              \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{%
                \ifthenelse{\endangle<\startangle}{%
                  \def\posAttrName{above left}%
                  \def\posMultiplicity{below right}%
                }{%
                  \def\posAttrName{above right}%
                  \def\posMultiplicity{below left}%
                }%
              }{%
                \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{%
                  \ifthenelse{\endangle<\startangle}{%
                    \def\posAttrName{above right}%
                    \def\posMultiplicity{below left}%
                  }{%
                    \def\posAttrName{above left}%
                    \def\posMultiplicity{below right}%
                  }%
                }{%
                  \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{%
                    \ifthenelse{\endangle<\startangle}{%
                      \def\posAttrName{above left}%
                      \def\posMultiplicity{below right}%
                    }{%
                      \def\posAttrName{above right}%
                      \def\posMultiplicity{below left}%
                    }%
                  }{%
                    \ifthenelse{\endangle<\startangle}{%
                      \def\posAttrName{above right}%
                      \def\posMultiplicity{below left}%
                    }{%
                      \def\posAttrName{above left}%
                      \def\posMultiplicity{below right}%
                    }%
                  }%
                }%
              }%
            }{}%
            %
            \ifnum\thepos>200%
              \pgfmathsetmacro{\pos}{(\thepos-200)/100}%
              \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                   node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}%
                                   }%
            \else%
              \ifnum\thepos<100%
                \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                     node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}%
                                     }%
              \else%
                \pgfmathsetmacro{\pos}{(\thepos-100)/100}%
                \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                       node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}%
                                      }%
              \fi%
            \fi%
            %
            \ifthenelse{\theposT=100}{%
              \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{%
                \ifthenelse{\endangle<\startangle}{%
                  \def\posAttrNameT{above right}%
                  \def\posMultiplicityT{below left}%
                }{%
                  \def\posAttrNameT{above left}%
                  \def\posMultiplicityT{below right}%
                }%
              }{%
                \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{%
                  \ifthenelse{\endangle<\startangle}{%
                    \def\posAttrNameT{above left}%
                    \def\posMultiplicityT{below right}%
                  }{%
                    \def\posAttrNameT{above right}%
                    \def\posMultiplicityT{below left}%
                  }%
                }{%
                  \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{%
                    \ifthenelse{\endangle<\startangle}{%
                      \def\posAttrNameT{above right}%
                      \def\posMultiplicityT{below left}%
                    }{%
                      \def\posAttrNameT{above left}%
                      \def\posMultiplicityT{below right}%
                    }%
                  }{%
                    \ifthenelse{\endangle<\startangle}{%
                      \def\posAttrNameT{above left}%
                      \def\posMultiplicityT{below right}%
                    }{%
                      \def\posAttrNameT{above right}%
                      \def\posMultiplicityT{below left}%
                    }%
                  }%
                }%
              }%
            }{}%
            %
            \ifthenelse{\theposT=200}{%
              \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{%
                \ifthenelse{\endangle<\startangle}{%
                  \def\posAttrNameT{above left}%
                  \def\posMultiplicityT{below right}%
                }{%
                  \def\posAttrNameT{above right}%
                  \def\posMultiplicityT{below left}%
                }%
              }{%
                \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{%
                  \ifthenelse{\endangle<\startangle}{%
                    \def\posAttrNameT{above right}%
                    \def\posMultiplicityT{below left}%
                  }{%
                    \def\posAttrNameT{above left}%
                    \def\posMultiplicityT{below right}%
                  }%
                }{%
                  \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{%
                    \ifthenelse{\endangle<\startangle}{%
                      \def\posAttrNameT{above left}%
                      \def\posMultiplicityT{below right}%
                    }{%
                      \def\posAttrNameT{above right}%
                      \def\posMultiplicityT{below left}%
                    }%
                  }{%
                    \ifthenelse{\endangle<\startangle}{%
                      \def\posAttrNameT{above right}%
                      \def\posMultiplicityT{below left}%
                    }{%
                      \def\posAttrNameT{above left}%
                      \def\posMultiplicityT{below right}%
                    }%
                  }%
                }%
              }%
            }{}%
            %
            \ifnum\theposT>200%
              \pgfmathsetmacro{\posT}{(\theposT-200)/100}%
              \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                   node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}%
                                   }%
            \else%
              \ifnum\theposT<100%
                \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                     node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}%
                                     }%
              \else%
                \pgfmathsetmacro{\posT}{(\theposT-100)/100}%
                \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                       node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}%
                                      }%
              \fi%
            \fi%
          \fi%
          %
          \ifthenelse{\equal{\tikzumlrecdirstart}{\tikzumlrecdirend}}{%
            \xdef\tikzumlPath{(\tikzumlSrcClassNodeName.\startangle) -- \tikzumlFirstArc (\relationName-2.center) -- \tikzumlMidOneArc (\relationName-4.center) -- \tikzumlLastArc (\tikzumlDestClassNodeName.\endangle) }%
            \ifnum\thetikzumlStateLevel>0%
              \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
              \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) (\relationName-4) (\relationName-5)}%
            \fi%
          }{%
            \xdef\tikzumlPath{(\tikzumlSrcClassNodeName.\startangle) -- \tikzumlFirstArc (\relationName-2.center) -- \tikzumlMidOneArc (\relationName-4.center) -- \tikzumlMidTwoArc (\relationName-6.center) -- \tikzumlLastArc (\tikzumlDestClassNodeName.\endangle) }%
            \ifnum\thetikzumlStateLevel>0%
              \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
              \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) (\relationName-4) (\relationName-5) (\relationName-6) (\relationName-7)}%
            \fi%
          }%
        }{}%
      }%
    }{%
      \def\arcNum{1}%
      \def\arcNumT{1}%
      %
      \node[inner sep=0] (\relationName-1) at (\relationName-middle) {};%
      \xdef\tikzumlLastArc{node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                           node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}%
                           node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                           node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}%
                           node[pos=\positionStereotype, anchor=center] {\stereotype} }%
      \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }%
      \ifnum\thetikzumlStateLevel>0%
        \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
        \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) }%
      \fi%
    }%
  }{%
    % first vertical then horizontal line
    \ifthenelse{\equal{\geometry}{|-}}%
    {%
      \def\tikzumlControlNodesNum{1}%
      %
      \def\tikzumlFirstArc{node[midway, inner sep=0, name=\relationName-1, anchor=center] {} }%
      \def\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-3, anchor=center]{} }%
      %
      \begin{pgfonlayer}{connections}%
      \node[inner sep=0] (\relationName-2) at (\tikzumlSrcClassNodeName\tikzumlSrcAnchor |- \tikzumlDestClassNodeName\tikzumlDestAnchor) {};%
      \end{pgfonlayer}%
      %
      \ifnum\theposStereo>100%
        \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}%
        \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }%
      \else%
        \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }%
      \fi%
      %
      \ifnum\thepos>100%
        \pgfmathsetmacro{\pos}{(\thepos-100)/100}%
        \def\arcNum{2}%
      \else%
        \def\arcNum{1}%
        \ifnum\thepos=100%
          \def\posAttrName{above left}%
          \def\posMultiplicity{below right}%
        \fi%
      \fi%
      %
      \ifnum\arcNum=1%
        \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                               node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
      \fi%
      \ifnum\arcNum=2%
        \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                             node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
      \fi%
      %
      \ifnum\theposT>100%
        \pgfmathsetmacro{\posT}{(\theposT-100)/100}%
        \def\arcNumT{2}%
      \else%
        \def\arcNumT{1}%
        \ifnum\theposT=100%
          \def\posAttrNameT{above left}%
          \def\posMultiplicityT{below right}%
        \fi%
      \fi%
      %
      \ifnum\arcNumT=1%
        \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                               node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
      \fi%
      \ifnum\arcNumT=2%
        \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                             node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
      \fi%
      %
      \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlFirstArc (\relationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }%
      \ifnum\thetikzumlStateLevel>0%
        \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
        \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) }%
      \fi%
    }{%
      % first horizontal then vertical line
      \ifthenelse{\equal{\geometry}{-|}}{%
        \def\tikzumlControlNodesNum{1}%
        %
        \def\tikzumlFirstArc{node[midway, inner sep=0, name=\relationName-1, anchor=center]{} }%
        \def\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-3, anchor=center] {} }%
        %
        \begin{pgfonlayer}{connections}%
        \node[inner sep=0] (\relationName-2) at (\tikzumlSrcClassNodeName\tikzumlSrcAnchor -| \tikzumlDestClassNodeName\tikzumlDestAnchor) {};%
        \end{pgfonlayer}%
        %
        \ifnum\theposStereo>100%
          \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}%
          \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }%
        \else%
          \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }%
        \fi%
        %
        \ifnum\thepos>100%
          \pgfmathsetmacro{\pos}{(\thepos-100)/100}%
          \def\arcNum{2}%
        \else%
          \def\arcNum{1}%
          \ifnum\thepos=100%
            \def\posAttrName{above left}%
            \def\posMultiplicity{below right}%
          \fi%
        \fi%
        %
        \ifnum\arcNum=1%
          \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                                 node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
        \fi%
        \ifnum\arcNum=2%
          \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                               node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
        \fi%
        %
        \ifnum\theposT>100%
          \pgfmathsetmacro{\posT}{(\theposT-100)/100}%
          \def\arcNumT{2}%
        \else%
          \def\arcNumT{1}%
          \ifnum\theposT=100%
            \def\posAttrNameT{above left}%
            \def\posMultiplicityT{below right}%
          \fi%
        \fi%
        %
        \ifnum\arcNumT=1%
          \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                                 node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
        \fi%
        \ifnum\arcNumT=2%
          \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                               node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
        \fi%
        %
        \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlFirstArc (\relationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }%
        \ifnum\thetikzumlStateLevel>0%
          \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
          \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) }%
        \fi%
      }{%
        % first vertical, then horizontal, finally vertical line
        \ifthenelse{\equal{\geometry}{|-|}}{%
          \def\tikzumlControlNodesNum{2}%
          %
          \def\tikzumlFirstArc{node[midway, inner sep=0, name=\relationName-1, anchor=center] {} }%
          \def\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-5, anchor=center] {} }%
          \def\tikzumlMidOneArc{ }%
          %
          \begin{pgfonlayer}{connections}%
          %
          \ifthenelse{\equal{\armO}{auto}}{%
            \ifthenelse{\equal{\armT}{auto}}{%
              \node[inner sep=0] (\relationName-3) at (\relationName-middle) {};%
              \node[inner sep=0] (\relationName-2) at (\tikzumlSrcClassNodeName\tikzumlSrcAnchor |- \relationName-3) {};%
              \node[inner sep=0] (\relationName-4) at (\relationName-3 -| \tikzumlDestClassNodeName\tikzumlDestAnchor) {};%
            }{%
              \draw (\tikzumlDestClassNodeName\tikzumlDestAnchor)+(0,\armT) node[inner sep=0, name=\relationName-4] {};%
              \node[inner sep=0] (\relationName-2) at (\relationName-4 -| \tikzumlSrcClassNodeName\tikzumlSrcAnchor) {};%
              \node[inner sep=0] (\relationName-3) at (barycentric cs:\relationName-2=0.5,\relationName-4=0.5) {};%
            }%
          }{%
            \draw (\tikzumlSrcClassNodeName\tikzumlSrcAnchor)+(0,\armO) node[inner sep=0, name=\relationName-2] {};%
            \node[inner sep=0] (\relationName-4) at (\relationName-2 -| \tikzumlDestClassNodeName\tikzumlDestAnchor) {};%
            \node[inner sep=0] (\relationName-3) at (barycentric cs:\relationName-2=0.5,\relationName-4=0.5) {};%
          }%
          \end{pgfonlayer}%
          %
          \ifnum\theposStereo>200%
            \pgfmathsetmacro{\posStereo}{(\theposStereo-200)/100}%
            \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }%
          \else%
            \ifnum\theposStereo<100%
              \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }%
            \else%
              \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}%
              \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posStereo, anchor=center] {\stereotype} }%
            \fi%
          \fi%
          %
          \ifthenelse{\thepos=200\OR\thepos=100}{%
            \def\posAttrName{above left}%
            \def\posMultiplicity{below right}%
          }{}%
          %
          \ifthenelse{\thepos>200}{%
            \pgfmathsetmacro{\pos}{(\thepos-200)/100}%
            \def\arcNum{3}%
          }{%
            \ifthenelse{\thepos<100}{%
              \def\arcNum{1}%
            }{%
              \pgfmathsetmacro{\pos}{(\thepos-100)/100}%
              \def\arcNum{2}%
            }%
          }%
          %
          \ifnum\arcNum=1%
            \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                                   node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
          \fi%
          \ifnum\arcNum=2%
            \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                                     node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
          \fi%
          \ifnum\arcNum=3%
            \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                                 node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
          \fi%
          %
          \ifthenelse{\theposT=200\OR\theposT=100}{%
            \def\posAttrNameT{above left}%
            \def\posMultiplicityT{below right}%
          }{}%
          %
          \ifthenelse{\theposT>200}{%
            \pgfmathsetmacro{\posT}{(\theposT-200)/100}%
            \def\arcNumT{3}%
          }{%
            \ifthenelse{\theposT<100}{%
              \def\arcNumT{1}%
            }{%
              \pgfmathsetmacro{\posT}{(\theposT-100)/100}%
              \def\arcNumT{2}%
            }%
          }%
          %
          \ifnum\arcNumT=1%
            \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                                   node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
          \fi%
          \ifnum\arcNumT=2%
            \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                                     node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
          \fi%
          \ifnum\arcNumT=3%
            \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                                 node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
          \fi%
          %
          \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlFirstArc (\relationName-2.base) -- \tikzumlMidOneArc (\relationName-4.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }%
          \ifnum\thetikzumlStateLevel>0%
            \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
            \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) (\relationName-4) (\relationName-5) }%
          \fi%
        }{%
          % first horizontal, then vertical, finally horizontal line
          \ifthenelse{\equal{\geometry}{-|-}}{%
            \def\tikzumlControlNodesNum{2}%
            %
            \def\tikzumlFirstArc{node[midway, inner sep=0, name=\relationName-1, anchor=center] {} }%
            \def\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-5, anchor=center] {} }%
            \def\tikzumlMidOneArc{}%
            %
            \begin{pgfonlayer}{connections}%
            %
            \ifthenelse{\equal{\armO}{auto}}{%
              \ifthenelse{\equal{\armT}{auto}}{%
                \node[inner sep=0] (\relationName-3) at (\relationName-middle) {};%
                \node[inner sep=0] (\relationName-2) at (\tikzumlSrcClassNodeName\tikzumlSrcAnchor -| \relationName-3) {};%
                \node[inner sep=0] (\relationName-4) at (\relationName-3 |- \tikzumlDestClassNodeName\tikzumlDestAnchor) {};%
              }{%
                \draw (\tikzumlDestClassNodeName\tikzumlDestAnchor)+(\armT,0) node[inner sep=0, name=\relationName-4] {};%
                \node[inner sep=0] (\relationName-2) at (\relationName-4 |- \tikzumlSrcClassNodeName\tikzumlSrcAnchor) {};%
                \node[inner sep=0] (\relationName-3) at (barycentric cs:\relationName-2=0.5,\relationName-4=0.5) {};%
              }%
            }{%
              \draw (\tikzumlSrcClassNodeName\tikzumlSrcAnchor)+(\armO,0) node[inner sep=0, name=\relationName-2] {};%
              \node[inner sep=0] (\relationName-4) at (\relationName-2 |- \tikzumlDestClassNodeName\tikzumlDestAnchor) {};%
              \node[inner sep=0] (\relationName-3) at (barycentric cs:\relationName-2=0.5,\relationName-4=0.5) {};%
            }%
            \end{pgfonlayer}%
            %
            %
            \ifnum\theposStereo>200%
              \pgfmathsetmacro{\posStereo}{(\theposStereo-200)/100}%
              \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }%
            \else%
              \ifnum\theposStereo<100%
                \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }%
              \else%
                \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}%
                \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posStereo, anchor=center] {\stereotype} }%
              \fi%
            \fi%
            %
            \ifthenelse{\thepos=200\OR\thepos=100}{%
              \def\posAttrName{above left}%
              \def\posMultiplicity{below right}%
            }{}%
            %
            \ifthenelse{\thepos>200}{%
              \pgfmathsetmacro{\pos}{(\thepos-200)/100}%
              \def\arcNum{3}%
            }{%
              \ifthenelse{\thepos<100}{%
                \def\arcNum{1}%
              }{%
                \pgfmathsetmacro{\pos}{(\thepos-100)/100}%
                \def\arcNum{2}%
              }%
            }%
            %
            \ifnum\arcNum=1%
              \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                                     node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
            \fi%
            \ifnum\arcNum=2%
              \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                                       node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
            \fi%
            \ifnum\arcNum=3%
              \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                                   node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
            \fi%
            %
            \ifthenelse{\theposT=200\OR\theposT=100}{%
              \def\posAttrNameT{above left}%
              \def\posMultiplicityT{below right}%
            }{}%
            %
            \ifthenelse{\theposT>200}{%
              \pgfmathsetmacro{\posT}{(\theposT-200)/100}%
              \def\arcNumT{3}%
            }{%
              \ifthenelse{\theposT<100}{%
                \def\arcNumT{1}%
              }{%
                \pgfmathsetmacro{\posT}{(\theposT-100)/100}%
                \def\arcNumT{2}%
              }%
            }%
            %
            \ifnum\arcNumT=1%
              \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                                     node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
            \fi%
            \ifnum\arcNumT=2%
              \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                                       node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
            \fi%
            \ifnum\arcNumT=3%
              \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                                   node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
            \fi%
            %
            \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlFirstArc (\relationName-2.base) -- \tikzumlMidOneArc (\relationName-4.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }%
            \ifnum\thetikzumlStateLevel>0%
              \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
              \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) (\relationName-4) (\relationName-5) }%
            \fi%
          }{%
            \errmessage{TIKZUML ERROR : Unknown geometry value !!! It should be in the following list : --, |-, -|, |-|, -|-}%
          }%
        }%
      }%
    }%
  }%
  %
  \begin{pgfonlayer}{connections}%
  \draw[auto, \style, font=\tikzumlfont] \tikzumlPath ;%
  \end{pgfonlayer}%
  %
  \stepcounter{tikzumlRelationNum}%
}%

% shortcuts of \umlrelation
\newcommand{\umlHVrelation}[3][]{%
  \pgfkeys{/tikzuml/HVrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
               \errmessage{TIKZUML ERROR : in umlHVrelation, forbidden option geometry}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/HVrelation/.cd, #1}%
  \umlrelation[geometry=-|, #1]{#2}{#3}%
}%

\newcommand{\umlVHrelation}[3][]{%
  \pgfkeys{/tikzuml/VHrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
               \errmessage{TIKZUML ERROR : in umlVHrelation, forbidden option geometry}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/VHrelation/.cd, #1}%
  \umlrelation[geometry=|-, #1]{#2}{#3}%
}%

\newcommand{\umlHVHrelation}[3][]{%
  \pgfkeys{/tikzuml/HVHrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
               \errmessage{TIKZUML ERROR : in umlHVHrelation, forbidden option geometry}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/HVHrelation/.cd, #1}%
  \umlrelation[geometry=-|-, #1]{#2}{#3}%
}%

\newcommand{\umlVHVrelation}[3][]{%
  \pgfkeys{/tikzuml/VHVrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
               \errmessage{TIKZUML ERROR : in umlVHVrelation, forbidden option geometry}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/VHVrelation/.cd, #1}%
  \umlrelation[geometry=|-|, #1]{#2}{#3}%
}%

% shortcuts for relations
\newcommand{\umlinherit}[3][]{\umlrelation[style={tikzuml inherit style}, #1]{#2}{#3}}%
\newcommand{\umlimpl}[3][]{\umlrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
\newcommand{\umlreal}[3][]{\umlrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
\newcommand{\umlassoc}[3][]{\umlrelation[style={tikzuml association style}, #1]{#2}{#3}}%
\newcommand{\umlbiassoc}[3][]{\umlrelation[style={tikzuml bidirectional association style}, #1]{#2}{#3}}%
\newcommand{\umluniassoc}[3][]{\umlrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}%
\newcommand{\umlaggreg}[3][]{\umlrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}%
\newcommand{\umluniaggreg}[3][]{\umlrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}%
\newcommand{\umlcompo}[3][]{\umlrelation[style={tikzuml composition style}, #1]{#2}{#3}}%
\newcommand{\umlunicompo}[3][]{\umlrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}%
\newcommand{\umlimport}[3][]{\umlrelation[style={tikzuml import style}, #1]{#2}{#3}}%
\newcommand{\umldep}[3][]{\umlrelation[style={tikzuml dependency style}, #1]{#2}{#3}}%
\newcommand{\umlfriend}[3][]{%
  \pgfkeys{/tikzuml/friendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlfriend, forbidden option stereo}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
  \umlrelation[stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}%
}%

\newcommand{\umlHVinherit}[3][]{\umlHVrelation[style={tikzuml inherit style}, #1]{#2}{#3}}%
\newcommand{\umlHVimpl}[3][]{\umlHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
\newcommand{\umlHVreal}[3][]{\umlHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
\newcommand{\umlHVassoc}[3][]{\umlHVrelation[style={tikzuml association style}, #1]{#2}{#3}}%
\newcommand{\umlHVuniassoc}[3][]{\umlHVrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}%
\newcommand{\umlHVaggreg}[3][]{\umlHVrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}%
\newcommand{\umlHVuniaggreg}[3][]{\umlHVrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}%
\newcommand{\umlHVcompo}[3][]{\umlHVrelation[style={tikzuml composition style}, #1]{#2}{#3}}%
\newcommand{\umlHVunicompo}[3][]{\umlHVrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}%
\newcommand{\umlHVimport}[3][]{\umlHVrelation[style={tikzuml import style}, #1]{#2}{#3}}%
\newcommand{\umlHVdep}[3][]{\umlHVrelation[style={tikzuml dependency style}, #1]{#2}{#3}}%
\newcommand{\umlHVfriend}[3][]{%
  \pgfkeys{/tikzuml/friendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlHVfriend, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlHVfriend, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
  \umlrelation[geometry=-|, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}%
}%

\newcommand{\umlVHinherit}[3][]{\umlVHrelation[style={tikzuml inherit style}, #1]{#2}{#3}}%
\newcommand{\umlVHimpl}[3][]{\umlVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
\newcommand{\umlVHreal}[3][]{\umlVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
\newcommand{\umlVHassoc}[3][]{\umlVHrelation[style={tikzuml association style}, #1]{#2}{#3}}%
\newcommand{\umlVHuniassoc}[3][]{\umlVHrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}%
\newcommand{\umlVHaggreg}[3][]{\umlVHrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}%
\newcommand{\umlVHuniaggreg}[3][]{\umlVHrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}%
\newcommand{\umlVHcompo}[3][]{\umlVHrelation[style={tikzuml composition style}, #1]{#2}{#3}}%
\newcommand{\umlVHunicompo}[3][]{\umlVHrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}%
\newcommand{\umlVHimport}[3][]{\umlVHrelation[style={tikzuml import style}, #1]{#2}{#3}}%
\newcommand{\umlVHdep}[3][]{\umlVHrelation[style={tikzuml dependency style}, #1]{#2}{#3}}%
\newcommand{\umlVHfriend}[3][]{%
  \pgfkeys{/tikzuml/friendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlVHfriend, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlVHfriend, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
  \umlrelation[geometry=|-, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}%
}%

\newcommand{\umlHVHinherit}[3][]{\umlHVHrelation[style={tikzuml inherit style}, #1]{#2}{#3}}%
\newcommand{\umlHVHimpl}[3][]{\umlHVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
\newcommand{\umlHVHreal}[3][]{\umlHVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
\newcommand{\umlHVHassoc}[3][]{\umlHVHrelation[style={tikzuml association style}, #1]{#2}{#3}}%
\newcommand{\umlHVHuniassoc}[3][]{\umlHVHrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}%
\newcommand{\umlHVHaggreg}[3][]{\umlHVHrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}%
\newcommand{\umlHVHuniaggreg}[3][]{\umlHVHrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}%
\newcommand{\umlHVHcompo}[3][]{\umlHVHrelation[style={tikzuml composition style}, #1]{#2}{#3}}%
\newcommand{\umlHVHunicompo}[3][]{\umlHVHrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}%
\newcommand{\umlHVHimport}[3][]{\umlHVHrelation[style={tikzuml import style}, #1]{#2}{#3}}%
\newcommand{\umlHVHdep}[3][]{\umlHVHrelation[style={tikzuml dependency style}, #1]{#2}{#3}}%
\newcommand{\umlHVHfriend}[3][]{%
  \pgfkeys{/tikzuml/friendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlHVHfriend, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlHVHfriend, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
  \umlrelation[geometry=-|-, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}%
}%

\newcommand{\umlVHVinherit}[3][]{\umlVHVrelation[style={tikzuml inherit style}, #1]{#2}{#3}}%
\newcommand{\umlVHVimpl}[3][]{\umlVHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
\newcommand{\umlVHVreal}[3][]{\umlVHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
\newcommand{\umlVHVassoc}[3][]{\umlVHVrelation[style={tikzuml association style}, #1]{#2}{#3}}%
\newcommand{\umlVHVuniassoc}[3][]{\umlVHVrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}%
\newcommand{\umlVHVaggreg}[3][]{\umlVHVrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}%
\newcommand{\umlVHVuniaggreg}[3][]{\umlVHVrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}%
\newcommand{\umlVHVcompo}[3][]{\umlVHVrelation[style={tikzuml composition style}, #1]{#2}{#3}}%
\newcommand{\umlVHVunicompo}[3][]{\umlVHVrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}%
\newcommand{\umlVHVimport}[3][]{\umlVHVrelation[style={tikzuml import style}, #1]{#2}{#3}}%
\newcommand{\umlVHVdep}[3][]{\umlVHVrelation[style={tikzuml dependency style}, #1]{#2}{#3}}%
\newcommand{\umlVHVfriend}[3][]{%
  \pgfkeys{/tikzuml/friendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlVHVfriend, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlVHVfriend, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
  \umlrelation[geometry=|-|, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}%
}%

% define a node
\newcommand{\umlnode}[2]{%
  \node (#2) at (#1) {};%
}%

% main command to define a relation between two classes through a control node
% args : src class
%        control node
%        dest class
% optional : geometry of the line
%            barycentric weight
%            name of the src class type attribute defined by the relation
%            multiplicity of the src class type attribute defined by the relation
%            position on the relation
%            text justification on the relation
%            name of the dest class type attribute defined by the relation
%            multiplicity of the dest class type attribute defined by the relation
%            position on the relation
%            border anchors 
%            text justification on the relation
%            start angle, end angle and size of the relation (only if recursive)
%            stereotype of the relation
%            style of the relation (association, aggregation, composition, inherit, ...)
\newcommand{\umlCNrelation}[4][]%
{%
  \pgfkeys{/tikzuml/relation/.cd,%
           arg1/.initial={}, arg2/.initial={}, arg/.initial={},%
           mult1/.initial={}, mult2/.initial={}, mult/.initial={},%
           pos1/.initial=0.2, pos2/.initial=0.8, pos/.initial={tikzumlEmpty},%
           align1/.initial={}, align2/.initial={}, align/.initial={},%
           anchor1/.initial={tikzumlEmpty}, anchor2/.initial={tikzumlEmpty},%
           stereo/.initial={}, pos stereo/.initial=1,%
           style/.initial=->, name/.initial=relation-\thetikzumlRelationNum,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlCNrelation, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/relation/.cd,#1}%
  \pgfkeys{/tikzuml/relation/.cd,%
           arg1/.get=\attrName, arg2/.get=\attrNameTO, arg/.get=\attrNameTT,%
           mult1/.get=\multiplicity, mult2/.get=\multiplicityTO, mult/.get=\multiplicityTT,%
           pos1/.get=\position, pos2/.get=\positionTO, pos/.get=\positionTT,%
           align1/.get=\align, align2/.get=\alignTO, align/.get=\alignTT,%
           anchor1/.get=\tikzumlSrcAnchor, anchor2/.get=\tikzumlDestAnchor,%
           stereo/.get=\stereo, pos stereo/.get=\positionStereotype,%
           style/.get=\style, name/.get=\relationName}%
  %
  % managing \_ in class names for node names
  \def\tikzumlSrcClassName{#2}%
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlSrcClassNodeName{\tikzumlSrcClassName}}\x%
  %
  \StrSubstitute{\tikzumlSrcClassNodeName}{:}{@COLON@}[\tikzumlSrcClassNodeName]
  %
  \def\tikzumlDestClassName{#4}%
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlDestClassNodeName{\tikzumlDestClassName}}\x%
  %
  \StrSubstitute{\tikzumlDestClassNodeName}{:}{@COLON@}[\tikzumlDestClassNodeName]
  %
  % managing alias keys
  \def\attrNameT{\attrNameTO\attrNameTT}%
  \def\multiplicityT{\multiplicityTO\multiplicityTT}%
  \def\alignT{\alignTO\alignTT}%
  \def\orientationT{\orientationTO\orientationTT}%
  %
  \ifthenelse{\equal{\positionTT}{tikzumlEmpty}}{%
    \def\positionT{\positionTO}%
  }{%
    \def\positionT{\positionTT}%
  }%
  %
  \def\attrAlign{}%
  \def\multAlign{}%
  \def\attrAlignT{}%
  \def\multAlignT{}%
  %
  \ifthenelse{\equal{\align}{left}}{%
    \def\attrAlign{above right}%
    \def\multAlign{below right}%
  }{%
    \ifthenelse{\equal{\align}{right}}{%
      \def\attrAlign{above left}%
      \def\multAlign{below left}%
    }{}%
  }%
  %
  \ifthenelse{\equal{\alignT}{left}}{%
    \def\attrAlignT{above right}%
    \def\multAlignT{below right}%
  }{%
    \ifthenelse{\equal{\alignT}{right}}{%
      \def\attrAlignT{above left}%
      \def\multAlignT{below left}%
    }{}%
  }%
  %
  % def stereotype
  \ifthenelse{\equal{\stereo}{}}{%
    \def\stereotype{}%
  }{%
    \def\stereotype{\guillemotleft\stereo\guillemotright}%
  }%
  %
  % def anchors macros
  \ifthenelse{\equal{\tikzumlSrcAnchor}{tikzumlEmpty}}{%
    \def\tikzumlSrcAnchor{}%
  }{%
    \let\tikzumlSrcAnchorold\tikzumlSrcAnchor%
    \def\tikzumlSrcAnchor{.\tikzumlSrcAnchorold}%
  }%
  %
  \ifthenelse{\equal{\tikzumlDestAnchor}{tikzumlEmpty}}{%
    \def\tikzumlDestAnchor{}%
  }{%
    \let\tikzumlDestAnchorold\tikzumlDestAnchor%
    \def\tikzumlDestAnchor{.\tikzumlDestAnchorold}%
  }%
  %
  \setcounter{pos}{100*\real{\position}}%
  \setcounter{posT}{100*\real{\positionT}}%
  \setcounter{posStereo}{100*\real{\positionStereotype}}%
  %
  \def\pos{\position}%
  \def\posT{\positionT}%
  \def\posStereo{\positionStereotype}%
  %
  % straight line
  \def\tikzumlControlNodesNum{1}%
  %
  \def\tikzumlFirstArc{node[midway, name=\relationName-1, anchor=center] {} }%
  \def\tikzumlLastArc{node[midway, name=\relationName-3, anchor=center]{} }%
  \def\posAttrName{}%
  \def\posMultiplicity{}%
  \def\posAttrNameT{}%
  \def\posMultiplicityT{}%
  %
  \begin{pgfonlayer}{connections}%
  \node (\relationName-2) at (#3) {};%
  \end{pgfonlayer}%
  %
  \ifnum\theposStereo>100%
    \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}%
    \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }%
  \else%
    \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }%
  \fi%
  %
  \ifnum\thepos>100%
    \pgfmathsetmacro{\pos}{(\thepos-100)/100}%
    \def\arcNum{2}%
  \else%
    \def\arcNum{1}%
    \ifnum\thepos=100%
      \def\posAttrName{above left}%
      \def\posMultiplicity{below right}%
    \fi%
  \fi%
  %
  \ifnum\arcNum=1%
    \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                           node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
  \fi%
  \ifnum\arcNum=2%
    \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}%
                                         node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }%
  \fi%
  %
  \ifnum\theposT>100%
    \pgfmathsetmacro{\posT}{(\theposT-100)/100}%
    \def\arcNumT{2}%
  \else%
    \def\arcNumT{1}%
    \ifnum\theposT=100%
      \def\posAttrNameT{above left}%
      \def\posMultiplicityT{below right}%
    \fi%
  \fi%
  %
  \ifnum\arcNumT=1%
    \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                           node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
  \fi%
  \ifnum\arcNumT=2%
    \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}%
                                         node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }%
  \fi%
  %
  \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlFirstArc (\relationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }%
  
  \begin{pgfonlayer}{connections}%
  \draw[auto, \style, font=\tikzumlfont] \tikzumlPath ;%
  \end{pgfonlayer}%
  %
  \stepcounter{tikzumlRelationNum}%
}%

% shortcuts for cnrelations
\newcommand{\umlCNinherit}[4][]{\umlCNrelation[style={tikzuml inherit style}, #1]{#2}{#3}{#4}}%
\newcommand{\umlCNimpl}[4][]{\umlCNrelation[style={tikzuml implements style}, #1]{#2}{#3}{#4}}%
\newcommand{\umlCNreal}[4][]{\umlCNrelation[style={tikzuml implements style}, #1]{#2}{#3}{#4}}%
\newcommand{\umlCNassoc}[4][]{\umlCNrelation[style={tikzuml association style}, #1]{#2}{#3}{#4}}%
\newcommand{\umlCNuniassoc}[4][]{\umlCNrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}{#4}}%
\newcommand{\umlCNaggreg}[4][]{\umlCNrelation[style={tikzuml aggregation style}, #1]{#2}{#3}{#4}}%
\newcommand{\umlCNuniaggreg}[4][]{\umlCNrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}{#4}}%
\newcommand{\umlCNcompo}[4][]{\umlCNrelation[style={tikzuml composition style}, #1]{#2}{#3}{#4}}%
\newcommand{\umlCNunicompo}[4][]{\umlCNrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}{#4}}%
\newcommand{\umlCNimport}[4][]{\umlCNrelation[style={tikzuml import style}, #1]{#2}{#3}{#4}}%
\newcommand{\umlCNdep}[4][]{\umlCNrelation[style={tikzuml dependency style}, #1]{#2}{#3}{#4}}%
\newcommand{\umlCNfriend}[4][]{%
  \pgfkeys{/tikzuml/friendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlCNfriend, forbidden option stereo}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
  \umlCNrelation[stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}{#4}%
}%

% define a note
% arg : attached class
%       label of the note
% optional : x,y coordinates of the note
%            width of the note
%            draw, fill, text colors
\newcommand{\umlnote}[3][]{
  \pgfkeys{/tikzuml/note/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=3cm, geometry/.initial=--,%
           weight/.initial=0.5, arm/.initial={auto},%
           anchor1/.initial={tikzumlEmpty}, anchor2/.initial={tikzumlEmpty},%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillnotecolor,%
           text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlnote, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/note/.cd, #1}%
  \pgfkeys{/tikzuml/note/.cd,%
           x/.get=\tikzumlnoteX, y/.get=\tikzumlnoteY, width/.get=\notetextwidth,%
           geometry/.get=\tikzumlnotegeometry,%
           weight/.get=\tikzumlnoteweight, arm/.get=\tikzumlnotearm,%
           anchor1/.get=\tikzumlnoteSrcAnchor, anchor2/.get=\tikzumlnoteDestAnchor,%
           draw/.get=\tikzumlnotedraw, fill/.get=\tikzumlnotefill,%
           text/.get=\tikzumlnotetext}%
  %
  \def\tikzumlClassName{#2}%
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlClassNodeName{\tikzumlClassName}}\x%
  %
  % def anchors macros
  \ifthenelse{\equal{\tikzumlnoteSrcAnchor}{tikzumlEmpty}}{%
    \def\tikzumlnoteSrcAnchor{}%
  }{%
    \let\tikzumlnoteSrcAnchorold\tikzumlnoteSrcAnchor%
    \def\tikzumlnoteSrcAnchor{.\tikzumlnoteSrcAnchorold}%
  }%
  %
  \ifthenelse{\equal{\tikzumlnoteDestAnchor}{tikzumlEmpty}}{%
    \def\tikzumlnoteDestAnchor{}%
  }{%
    \let\tikzumlnoteDestAnchorold\tikzumlnoteDestAnchor%
    \def\tikzumlnoteDestAnchor{.\tikzumlnoteDestAnchorold}%
  }%
  %
  \node[text=\tikzumlnotetext, text width=\notetextwidth, font=\tikzumlfont, outer sep=0, inner xsep=1ex, inner ysep=3ex] (note-\thetikzumlNoteNum-coord) at (\tikzumlnoteX, \tikzumlnoteY) {#3};%
  \draw (note-\thetikzumlNoteNum-coord.north east) node[name=note-\thetikzumlNoteNum-right-top, below=2ex, coordinate] {};%
  \draw (note-\thetikzumlNoteNum-coord.north east) node[name=note-\thetikzumlNoteNum-top-right, left=2ex, coordinate] {};%
  \draw[draw=\tikzumlnotedraw, fill=\tikzumlnotefill] (note-\thetikzumlNoteNum-coord.south west) -- (note-\thetikzumlNoteNum-coord.south east) -- (note-\thetikzumlNoteNum-right-top.base) -- (note-\thetikzumlNoteNum-top-right.base) -- (note-\thetikzumlNoteNum-coord.north west) -- cycle;%
  \node[text=\tikzumlnotetext, text width=\notetextwidth, outer sep=0, inner xsep=1ex, inner ysep=3ex, font=\tikzumlfont] (note-\thetikzumlNoteNum) at (note-\thetikzumlNoteNum-coord) {#3};%
    \draw[draw=\tikzumlnotedraw] (note-\thetikzumlNoteNum-right-top) -| (note-\thetikzumlNoteNum-top-right);%
  %
  \pgfmathsetmacro{\tikzumlnoteweightT}{1-\tikzumlnoteweight}%
  \node (note-\thetikzumlNoteNum-middle) at (barycentric cs:note-\thetikzumlNoteNum-coord=\tikzumlnoteweight,\tikzumlClassNodeName=\tikzumlnoteweightT) {};%
  %
  \ifthenelse{\equal{\tikzumlnotegeometry}{--}%
           \OR\equal{\tikzumlnotegeometry}{-|}%
           \OR\equal{\tikzumlnotegeometry}{|-}}{%
    \edef\tikzumlnotepath{\tikzumlnotegeometry}
  }{%
    \ifthenelse{\equal{\tikzumlnotegeometry}{-|-}}{%
      \ifthenelse{\equal{\tikzumlnotearm}{auto}}{%
        \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-coord\tikzumlnoteSrcAnchor -| note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center |- \tikzumlClassNodeName\tikzumlnoteDestAnchor) --}%
      }{%
        \draw (note-\thetikzumlNoteNum-coord\tikzumlnoteSrcAnchor)+(\tikzumlnotearm,0) node[name=note-\thetikzumlNoteNum-tmp] {};
        \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-tmp.center) |-}%
      }%
    }{%
      \ifthenelse{\equal{\tikzumlnotegeometry}{|-|}}{%
        \ifthenelse{\equal{\tikzumlnotearm}{auto}}{%
        \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-coord\tikzumlnoteSrcAnchor |- note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center -| \tikzumlClassNodeName\tikzumlnoteDestAnchor) --}%
      }{%
        \draw (note-\thetikzumlNoteNum-coord\tikzumlnoteSrcAnchor)+(0,\tikzumlnotearm) node[name=note-\thetikzumlNoteNum-tmp] {};
        \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-tmp.center) -|}%
      }%
      
      }{%
        \errmessage{TIKZUML ERROR : Unknown geometry value !!! It should be in the following list : --, |-, -|, |-|, -|-}%
      }%
    }%
  }%
  %
  \begin{pgfonlayer}{connections}%
  \draw[dashed] (note-\thetikzumlNoteNum-coord\tikzumlnoteSrcAnchor) \tikzumlnotepath (\tikzumlClassNodeName\tikzumlnoteDestAnchor);%
  \end{pgfonlayer}%
  %
  \stepcounter{tikzumlNoteNum}%
}%

% shortcuts for note with geometry
\newcommand{\umlHVnote}[3][]{%
  \pgfkeys{/tikzuml/note/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
               \errmessage{TIKZUML ERROR : in umlHVnote, forbidden option geometry}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/note/.cd, #1}%
  \umlnote[geometry=-|, #1]{#2}{#3}%
}%
\newcommand{\umlVHnote}[3][]{%
  \pgfkeys{/tikzuml/note/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
               \errmessage{TIKZUML ERROR : in umlVHnote, forbidden option geometry}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/note/.cd, #1}%
  \umlnote[geometry=|-, #1]{#2}{#3}%
}%
\newcommand{\umlVHVnote}[3][]{%
  \pgfkeys{/tikzuml/note/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
               \errmessage{TIKZUML ERROR : in umlVHVnote, forbidden option geometry}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/note/.cd, #1}%
  \umlnote[geometry=|-|, #1]{#2}{#3}%
}%
\newcommand{\umlHVHnote}[3][]{%
  \pgfkeys{/tikzuml/note/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
               \errmessage{TIKZUML ERROR : in umlHVHnote, forbidden option geometry}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/note/.cd, #1}%
  \umlnote[geometry=-|-, #1]{#2}{#3}%
}%

% define a uml association class (command)
% args : name of the class
%        attributes of the class
%        operations of the class
% optional : x,y coordinates of the class
%            width of the class node
%            type of class (class, interface, typedef, enum)
%            template parameters
%            draw, fill, text colors
\newcommand{\umlassocclass}[5][]{%
  \pgfkeys{/tikzuml/assocclass/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=10ex, type/.initial=class,%
           template/.initial={}, name/.initial={tikzumlEmpty}, geometry/.initial=--,%
           weight/.initial=0.5, arm/.initial={auto},%
           anchor1/.initial={tikzumlEmpty}, anchor2/.initial={tikzumlEmpty},%
           draw/.initial=\tikzumldrawcolor,%
           fill template/.initial=\tikzumlfilltemplatecolor,%
           fill/.initial=\tikzumlfillclasscolor,%
           text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlassocclass, invalid option \keyname}%
           }}%
  %
  \pgfkeys{/tikzuml/assocclass/.cd,#1}%
  \pgfkeys{/tikzuml/assocclass/.cd,%
           x/.get=\umlassocclassX, y/.get=\umlassocclassY,%
           width/.get=\umlassocclassMinimumWidth, type/.get=\umlassocclassType,%
           template/.get=\umlassocclassTemplateParam,%
           name/.get=\umlassocclassName, geometry/.get=\tikzumlassocclassgeometry,%
           weight/.get=\tikzumlassocclassweight, arm/.get=\tikzumlassocclassarm,%
           anchor1/.get=\tikzumlassocclassSrcAnchor,%
           anchor2/.get=\tikzumlassocclassDestAnchor,%
           draw/.get=\tikzumlassocclassdraw, fill/.get=\tikzumlassocclassfill,%
           text/.get=\tikzumlassocclasstext, fill template/.get=\tikzumlassocclasstemplate}%
  %
  \ifthenelse{\equal{\umlassocclassType}{class}\OR\equal{\umlassocclassType}{abstract}}{%
    \def\tikzumlAssocClassType{}%
  }{%
    \def\tikzumlAssocClassType{\guillemotleft\umlassocclassType\guillemotright \\}%
  }%
  %
  \ifthenelse{\equal{\umlassocclassTemplateParam}{}}{%
    \def\tikzumlAssocClassVPadding{}%
    \def\tikzumlAssocClassHPadding{}%
  }{%
    \def\tikzumlAssocClassVPadding{\vspace{0.1em} \\}%
    \def\tikzumlAssocClassHPadding{\hspace{0.5ex} $ $}%
  }%
  %
  \def\tikzumlAssocClassName{#2}%
  \def\tikzumlAssocClassRelationName{#3}%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlAssocClassNodeName{\tikzumlAssocClassName}}\x%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlAssocClassRelationNodeName{\tikzumlAssocClassRelationName}}\x%
  %
  \ifthenelse{\equal{\umlassocclassName}{tikzumlEmpty}}{}{%
    \def\tikzumlAssocClassNodeName{\umlassocclassName}%
  }%
  %
  \StrSubstitute{\tikzumlAssocClassNodeName}{:}{@COLON@}[\tikzumlAssocClassNodeName]
  %
  \ifthenelse{\equal{\umlassocclassType}{abstract}}{%
    \let\tikzumlAssocClassNameOld\tikzumlAssocClassName%
    \def\tikzumlAssocClassName{{\it \tikzumlAssocClassNameOld}}%
  }{}%
  %
  \def\tikzumlAssocClassPos{\umlassocclassX,\umlassocclassY}%
  \def\tikzumlAssocClassAttributes{#4}%
  \def\tikzumlAssocClassOperations{#5}%
  %
  % def anchors macros
  \ifthenelse{\equal{\tikzumlassocclassSrcAnchor}{tikzumlEmpty}}{%
    \def\tikzumlassocclassSrcAnchor{}%
  }{%
    \let\tikzumlassocclassSrcAnchorold\tikzumlassocclassSrcAnchor%
    \def\tikzumlassocclassSrcAnchor{.\tikzumlassocclassSrcAnchorold}%
  }%
  %
  \ifthenelse{\equal{\tikzumlassocclassDestAnchor}{tikzumlEmpty}}{%
    \def\tikzumlassocclassDestAnchor{}%
  }{%
    \let\tikzumlassocclassDestAnchorold\tikzumlassocclassDestAnchor%
    \def\tikzumlassocclassDestAnchor{.\tikzumlassocclassDestAnchorold}%
  }%
  %
  \node[tikzuml class style, draw=\tikzumlassocclassdraw, fill=\tikzumlassocclassfill, text=\tikzumlassocclasstext, font=\tikzumlfont, minimum width=\umlassocclassMinimumWidth] (\tikzumlAssocClassNodeName) at (\tikzumlAssocClassPos) {\begin{tabular}{c}\tikzumlAssocClassVPadding \tikzumlAssocClassType \tikzumlAssocClassHPadding \textbf{\tikzumlAssocClassName} \tikzumlAssocClassHPadding \end{tabular}%
  \nodepart{second}%
  \begin{tabular}{l}%
  \tikzumlAssocClassAttributes%
  \end{tabular}%
  \nodepart{third}%
  \begin{tabular}{l}%
  \tikzumlAssocClassOperations%
  \end{tabular}%
  };%
  %
  \ifthenelse{\equal{\umlassocclassTemplateParam}{}}{}{%
    \draw (\tikzumlAssocClassNodeName.north east) node[tikzuml template style, name=\tikzumlAssocClassNodeName-template, draw=\tikzumlassocclassdraw, fill=\tikzumlassocclasstemplate, text=\tikzumlassocclasstext, font=\tikzumlfont] {\umlassocclassTemplateParam};%
  }%
  %
  \pgfmathsetmacro{\tikzumlassocclassweightT}{1-\tikzumlassocclassweight}
  \node (\tikzumlAssocClassNodeName-middle) at (barycentric cs:\tikzumlAssocClassNodeName=\tikzumlassocclassweight,\tikzumlAssocClassRelationNodeName=\tikzumlassocclassweightT) {};%
  %
  \ifthenelse{\equal{\tikzumlassocclassgeometry}{--}\OR\equal{\tikzumlassocclassgeometry}{-|}\OR\equal{\tikzumlassocclassgeometry}{|-}}{%
    \edef\tikzumlassocclasspath{\tikzumlassocclassgeometry}
  }{%
    \ifthenelse{\equal{\tikzumlassocclassgeometry}{-|-}}{%
      \ifthenelse{\equal{\tikzumlassocclassarm}{auto}}{%
        \edef\tikzumlassocclasspath{-- (\tikzumlAssocClassNodeName\tikzumlassocclassSrcAnchor -| \tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center |- \tikzumlAssocClassRelationNodeName\tikzumlassocclassDestAnchor) --}%
      }{%
        \draw (\tikzumlAssocClassNodeName\tikzumlassocclassSrcAnchor)+(\tikzumlassocclassarm,0) node[name=\tikzumlAssocClassNodeName-tmp] {};
        \edef\tikzumlnotepath{-- (\tikzumlAssocClassNodeName-tmp.center) |-}%
      }%
    }{%
      \ifthenelse{\equal{\tikzumlassocclassgeometry}{|-|}}{%
        \ifthenelse{\equal{\tikzumlassocclassarm}{auto}}{%
        \edef\tikzumlassocclasspath{-- (\tikzumlAssocClassNodeName\tikzumlassocclassSrcAnchor |- \tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center -| \tikzumlAssocClassRelationNodeName\tikzumlassocclassDestAnchor) --}%
      }{%
        \draw (\tikzumlAssocClassNodeName\tikzumlassocclassSrcAnchor)+(0,\tikzumlassocclassarm) node[name=\tikzumlAssocClassNodeName-tmp] {};
        \edef\tikzumlassocclasspath{-- (\thetikzumlAssocClassNodeName-tmp.center) -|}%
      }%
      
      }{%
        \errmessage{TIKZUML ERROR : Unknown geometry value !!! It should be in the following list : --, |-, -|, |-|, -|-}%
      }%
    }%
  }%
  %
  \begin{pgfonlayer}{connections}%
  \draw[dashed] (\tikzumlAssocClassNodeName\tikzumlassocclassSrcAnchor) \tikzumlassocclasspath (\tikzumlAssocClassRelationNodeName\tikzumlassocclassDestAnchor);%
  \end{pgfonlayer}%
  %


  %
  % add to fit
  \ifnum\c@tikzumlPackageLevel>0%
    \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}%
    \ifthenelse{\equal{\umlassocclassTemplateParam}{}}{%
      \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlAssocClassNodeName)(\tikzumlAssocClassNodeName-middle)}%
    }{%
      \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlAssocClassNodeName) (\tikzumlAssocClassNodeName-template)(\tikzumlAssocClassNodeName-middle)}%
    }%
    \stepcounter{tikzumlPackageClassNum}%
  \fi%
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                     use case diagrams                   %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\tikzstyle{tikzuml usecase style}=[ellipse, text centered]%
\tikzstyle{tikzuml actor style}=[ellipse, inner sep=0, outer sep=0]%

\newcounter{tikzumlSystemUseCaseNum}%
\newcounter{tikzumlSystemLevel}%
\newcounter{tikzumlUseCaseNum}%
\newcounter{tikzumlActorNum}%

% define a system
% arg : name
% optional : x, y coordinates of the system
%            draw, fill, text colors
\newenvironment{umlsystem}[2][]{%
  \gdef\tikzumlSystemFit{}%
  \def\tikzumlSystemName{#2}%
  \setcounter{tikzumlSystemUseCaseNum}{0}%
  %
  \pgfkeys{/tikzuml/system/.cd,%
           x/.initial=0, y/.initial=0, x/.default=0, y/.default=0,%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillsystemcolor,%
           text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlsystem, invalid option \keyname}%
           }}%
  %
  \pgfkeys{/tikzuml/system/.cd, #1}%
  \pgfkeys{/tikzuml/system/.cd,%
           x/.get=\xshift, y/.get=\yshift,%
           draw/.get=\tikzumlsystemdraw, fill/.get=\tikzumlsystemfill,%
           text/.get=\tikzumlsystemtext}%
  %
  \stepcounter{tikzumlSystemLevel}%
  %
  \begin{scope}[xshift=\xshift cm, yshift=\yshift cm]%
}{%
  \addtocounter{tikzumlSystemLevel}{-1}%
  % if contains no usecase, one define a fictive node to enable the fit option
  \ifnum\c@tikzumlSystemUseCaseNum=0%
    \node[inner xsep=10ex, inner ysep=1em] (\tikzumlSystemName-root) at (0,0) {};%
    \xdef\tikzumlSystemFit{(\tikzumlSystemName-root)}%
  \fi%
  %
  \begin{pgfonlayer}{background}%
  \node[inner ysep=1em, inner xsep=2ex, fit = \tikzumlSystemFit] (\tikzumlSystemName-tmp) {};%
  \node[text=\tikzumlsystemtext, font=\tikzumlfont] (\tikzumlSystemName-caption-tmp) at (\tikzumlSystemName-tmp.north) {\tikzumlSystemName};%
  \node[draw=\tikzumlsystemdraw, fill=\tikzumlsystemfill, text=\tikzumlsystemtext, font=\tikzumlfont, inner ysep=1em, inner xsep=2ex, fit = (\tikzumlSystemName-tmp) (\tikzumlSystemName-caption-tmp)] (\tikzumlSystemName) {};%
  \node[text=\tikzumlsystemtext, font=\tikzumlfont] (\tikzumlSystemName-caption) at (\tikzumlSystemName-caption-tmp.north) {\tikzumlSystemName};%
  \end{pgfonlayer}%
  \end{scope}%
  %
}%

% define a use case
% arg : label of the use case
% optional : x, y coordinates of the use case
%            name of the node
%            draw, fill, text colors
\newcommand{\umlusecase}[2][]{%
  \stepcounter{tikzumlUseCaseNum}%
  \pgfkeys{/tikzuml/usecase/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=auto,%
           name/.initial=usecase-\thetikzumlUseCaseNum,%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillusecasecolor,%
           text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlusecase, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/usecase/.cd, #1}%
  \pgfkeys{/tikzuml/usecase/.cd,%
           x/.get=\posx, y/.get=\posy, width/.get=\tikzumlusecasetextwidth,%
           name/.get=\usecaseName,%
           draw/.get=\tikzumlusecasedraw, fill/.get=\tikzumlusecasefill,%
           text/.get=\tikzumlusecasetext}%
  %
  \def\tikzumlUseCaseText{#2}%
  %
  \def\tikzumlUseCasePos{\posx,\posy}%
  %
  \ifthenelse{\equal{\tikzumlusecasetextwidth}{auto}}{%
    \node[tikzuml usecase style, draw=\tikzumlusecasedraw, fill=\tikzumlusecasefill, text=\tikzumlusecasetext, font=\tikzumlfont] (\usecaseName) at (\tikzumlUseCasePos) {\tikzumlUseCaseText};%
  }{%
    \node[tikzuml usecase style, draw=\tikzumlusecasedraw, fill=\tikzumlusecasefill, text=\tikzumlusecasetext, font=\tikzumlfont, text width=\tikzumlusecasetextwidth] (\usecaseName) at (\tikzumlUseCasePos) {\tikzumlUseCaseText};%
  }%
  %
  % add to fit
  \ifnum\c@tikzumlSystemLevel>0%
    \let\tikzumlSystemFitOld\tikzumlSystemFit%
    \xdef\tikzumlSystemFit{\tikzumlSystemFitOld (\usecaseName)}%
    \stepcounter{tikzumlSystemUseCaseNum}%
  \fi%
}%

% define the actor symbol
% optional : global tikzpicture styles
\newcommand{\picturedactor}[1]{%
  \pgfkeys{/tikzuml/picactor/.cd, scale/.initial=1, .unknown/.code={}}%
  \pgfkeys{/tikzuml/picactor/.cd,#1}%
  \pgfkeys{/tikzuml/picactor/.cd, scale/.get=\tikzumlpicactorscale}%
  %
  \begin{tikzpicture}[#1]
  \coordinate (head) at (0,4ex);
  \coordinate (left-hand) at (-2ex,2ex);
  \coordinate (right-hand) at (2ex,2ex);
  \coordinate (left-foot) at (-2ex,-2ex);
  \coordinate (right-foot) at (2ex,-2ex);
  \coordinate (empty) at (0,-3ex);
  \draw (empty) (0,0) -- (head);
  \draw (left-hand) -- (right-hand);
  \draw (0,0) -- (left-foot) (0,0) -- (right-foot);
  \node[fill, draw, circle, inner sep=\tikzumlpicactorscale*0.3333ex, minimum size=\tikzumlpicactorscale*2ex] at (head) {};
  \end{tikzpicture}
}%

% define an actor
% arg : var name
% optional : x, y coordinates of the actor
%            name of the node
%            draw, text colors
\newcommand{\umlactor}[2][]{%
  \stepcounter{tikzumlActorNum}%
  \pgfkeys{/tikzuml/actor/.cd,%
           x/.initial=0, y/.initial=0, scale/.initial=1, below/.initial=0.5cm,%
           draw/.initial=\tikzumldrawcolor, text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlactor, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/actor/.cd, #1}%
  \pgfkeys{/tikzuml/actor/.cd,%
           x/.get=\posx, y/.get=\posy, scale/.get=\tikzumlactorscale,%
           below/.get=\tikzumlactorbelow,%
           draw/.get=\tikzumlactordraw, text/.get=\tikzumlactortext}%
  %
  \def\tikzumlActorName{#2}%
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlActorNodeName{\tikzumlActorName}}\x%
  %
  \def\tikzumlActorPos{\posx,\posy}%
  %
  \ifthenelse{\equal{}{tikzumlEmpty}}{}{}
  \node[tikzuml actor style, text=\tikzumlactortext, font=\tikzumlfont] (\tikzumlActorNodeName) at (\tikzumlActorPos) {\picturedactor{scale=\tikzumlactorscale, fill=white, draw=\tikzumlactordraw, thick}};%
  \node[text=\tikzumlactortext, font=\tikzumlfont, below=\tikzumlactorscale*\tikzumlactorbelow] at (\tikzumlActorNodeName) {\tikzumlActorName};%
  %
}%

% shortcuts for include and extend relation
\newcommand{\umlinclude}[3][]{%
  \pgfkeys{/tikzuml/includerelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlinclude, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlinclude, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/includerelation/.cd, #1}%
  \umlrelation[stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}%
}%
\newcommand{\umlextend}[3][]{%
  \pgfkeys{/tikzuml/extendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlextend, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlextend, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
  \umlrelation[stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}%
}%

\newcommand{\umlHVinclude}[3][]{%
  \pgfkeys{/tikzuml/includerelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlHVinclude, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlHVinclude, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/includerelation/.cd, #1}%
  \umlrelation[geometry=-|, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}%
}%
\newcommand{\umlHVextend}[3][]{%
  \pgfkeys{/tikzuml/extendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlHVextend, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlHVextend, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
  \umlrelation[geometry=-|, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}%
}%

\newcommand{\umlVHinclude}[3][]{%
  \pgfkeys{/tikzuml/includerelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlVHinclude, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlVHinclude, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/includerelation/.cd, #1}%
  \umlrelation[geometry=|-, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}%
}%
\newcommand{\umlVHextend}[3][]{%
  \pgfkeys{/tikzuml/extendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR :in umlVHextend,  forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlVHextend, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
  \umlrelation[geometry=|-, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}%
}%

\newcommand{\umlHVHinclude}[3][]{%
  \pgfkeys{/tikzuml/includerelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlHVHinclude, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlHVHinclude, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/includerelation/.cd, #1}%
  \umlrelation[geometry=-|-, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}%
}%
\newcommand{\umlHVHextend}[3][]{%
  \pgfkeys{/tikzuml/extendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlHVHextend, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlHVHextend, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
  \umlrelation[geometry=-|-, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}%
}%

\newcommand{\umlVHVinclude}[3][]{%
  \pgfkeys{/tikzuml/includerelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlVHVinclude, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlVHVinclude, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/includerelation/.cd, #1}%
  \umlrelation[geometry=|-|, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}%
}%
\newcommand{\umlVHVextend}[3][]{%
  \pgfkeys{/tikzuml/extendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlVHVextend, forbidden option stereo}%
             }{%
               \ifthenelse{\equal{\keyname}{geometry}}{%
                 \errmessage{TIKZUML ERROR : in umlVHVextend, forbidden option geometry}%
               }{}%
             }%
           }}%
  \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
  \umlrelation[geometry=|-|, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}%
}%

\newcommand{\umlCNinclude}[4][]{%
  \pgfkeys{/tikzuml/includerelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlCNinclude, forbidden option stereo}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/includerelation/.cd, #1}%
  \umlCNrelation[stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}{#4}%
}%

\newcommand{\umlCNextend}[4][]{%
  \pgfkeys{/tikzuml/extendrelation/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlCNextend, forbidden option stereo}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
  \umlCNrelation[stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}{#4}%
}%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                      state diagrams                     %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\tikzstyle{tikzuml state style}=[rectangle split, rectangle split parts=2, rounded corners, inner xsep=1.5ex]%
\tikzstyle{tikzuml transition style}=[color=\tikzumldrawcolor, rounded corners, -angle 45]%

\newcounter{tikzumlStateJoinNum}%
\newcounter{tikzumlStateDecisionNum}%
\newcounter{tikzumlStateInitialNum}%
\newcounter{tikzumlStateFinalNum}%
\newcounter{tikzumlStateEnterNum}%
\newcounter{tikzumlStateExitNum}%
\newcounter{tikzumlStateEndNum}%
\newcounter{tikzumlStateHistoryNum}%
\newcounter{tikzumlStateDeepHistoryNum}%
\newcounter{tikzumlStateLevel}%
\newcounter{tikzumlStateSubStateNum}%
\newcounter{tikzumlStateText}%

\newcommand{\umlstatejoin}[1][]{%
  \pgfkeys{/tikzuml/statejoin/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=3ex,%
           name/.initial=statejoin-\thetikzumlStateJoinNum,%
           color/.initial=\tikzumldrawcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlstatejoin, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/statejoin/.cd, #1}%
  \pgfkeys{/tikzuml/statejoin/.cd,%
           x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstatejoinwidth,%
           name/.get=\tikzumlstatejoinname, color/.get=\tikzumlstatejoincolor}%
  %
  \def\tikzumlStateJoinPos{\posx,\posy}%
  %
  \node[circle, minimum size=\tikzumlstatejoinwidth, draw=\tikzumlstatejoincolor, fill=\tikzumlstatejoincolor] (\tikzumlstatejoinname) at (\tikzumlStateJoinPos) {};%
  %
  % add to fit
  \ifnum\c@tikzumlStateLevel>0%
    \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
    \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstatejoinname)}%
    \stepcounter{tikzumlStateSubStateNum}%
  \fi%
  \stepcounter{tikzumlStateJoinNum}%
}%

\newcommand{\umlstatedecision}[1][]{%
  \pgfkeys{/tikzuml/statedecision/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=3ex,%
           name/.initial=statedecision-\thetikzumlStateDecisionNum,%
           color/.initial=\tikzumldrawcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlstatedecision, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/statedecision/.cd, #1}%
  \pgfkeys{/tikzuml/statedecision/.cd,%
           x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstatedecisionwidth,%
           name/.get=\tikzumlstatedecisionname, color/.get=\tikzumlstatedecisioncolor}%
  %  
  \def\tikzumlStateDecisionPos{\posx,\posy}%
  %
  \node[rectangle, rotate=45, minimum size=\tikzumlstatedecisionwidth, draw=\tikzumlstatedecisioncolor] (\tikzumlstatedecisionname) at (\tikzumlStateDecisionPos) {};%
  %
  % add to fit
  \ifnum\c@tikzumlStateLevel>0%
    \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
    \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstatedecisionname)}%
    \stepcounter{tikzumlStateSubStateNum}%
  \fi%
  \stepcounter{tikzumlStateDecisionNum}%
}%

\newcommand{\umlstateinitial}[1][]{%
  \pgfkeys{/tikzuml/stateinitial/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=5ex,%
           name/.initial=stateinitial-\thetikzumlStateInitialNum,%
           color/.initial=\tikzumldrawcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlstateinitial, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/stateinitial/.cd, #1}%
  \pgfkeys{/tikzuml/stateinitial/.cd,%
           x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstateinitialwidth,%
           name/.get=\tikzumlstateinitialname, color/.get=\tikzumlstateinitialcolor}%
  %  
  \def\tikzumlStateInitialPos{\posx,\posy}%
  %
  \node[circle, minimum size=\tikzumlstateinitialwidth, fill=\tikzumlstateinitialcolor] (\tikzumlstateinitialname) at (\tikzumlStateInitialPos) {};%
  %
  % add to fit
  \ifnum\c@tikzumlStateLevel>0%
    \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
    \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstateinitialname)}%
    \stepcounter{tikzumlStateSubStateNum}%
  \fi%
  \stepcounter{tikzumlStateInitialNum}%
}%

\newcommand{\umlstatefinal}[1][]{%
  \pgfkeys{/tikzuml/statefinal/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=5.5ex,%
           name/.initial=statefinal-\thetikzumlStateFinalNum,%
           color/.initial=\tikzumldrawcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlstatefinal, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/statefinal/.cd, #1}%
  \pgfkeys{/tikzuml/statefinal/.cd, x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstatefinalwidth,%
                                       name/.get=\tikzumlstatefinalname, color/.get=\tikzumlstatefinalcolor}%
  %  
  \def\tikzumlStateFinalPos{\posx,\posy}%
  %
  \node[circle, minimum size=\tikzumlstatefinalwidth, draw=\tikzumlstatefinalcolor, fill=\tikzumlstatefinalcolor, double, double distance=0.1cm] (\tikzumlstatefinalname) at (\tikzumlStateFinalPos) {};%
  %
  % add to fit
  \ifnum\c@tikzumlStateLevel>0%
    \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
    \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstatefinalname)}%
    \stepcounter{tikzumlStateSubStateNum}%
  \fi%
  \stepcounter{tikzumlStateFinalNum}%
}%

\newcommand{\umlstateenter}[1][]{%
  \pgfkeys{/tikzuml/stateenter/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=5ex,%
           name/.initial=stateenter-\thetikzumlStateEnterNum,%
           color/.initial=\tikzumldrawcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlstateenter, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/stateenter/.cd, #1}%
  \pgfkeys{/tikzuml/stateenter/.cd,%
           x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstateenterwidth,%
           name/.get=\tikzumlstateentername, color/.get=\tikzumlstateentercolor}%
  %  
  \def\tikzumlStateEnterPos{\posx,\posy}%
  %
  \node[circle, minimum size=\tikzumlstateenterwidth, draw=\tikzumlstateentercolor] (\tikzumlstateentername) at (\tikzumlStateEnterPos) {};%
  %
  % add to fit
  \ifnum\c@tikzumlStateLevel>0%
    \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
    \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstateentername)}%
    \stepcounter{tikzumlStateSubStateNum}%
  \fi%
  \stepcounter{tikzumlStateEnterNum}%
}%

\newcommand{\umlstateexit}[1][]{%
  \pgfkeys{/tikzuml/stateexit/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=5ex,%
           name/.initial=stateexit-\thetikzumlStateExitNum,%
           color/.initial=\tikzumldrawcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlstateexit, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/stateexit/.cd, #1}%
  \pgfkeys{/tikzuml/stateexit/.cd,%
           x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstateexitwidth,%
           name/.get=\tikzumlstateexitname, color/.get=\tikzumlstateexitcolor}%
  %  
  \def\tikzumlStateExitPos{\posx,\posy}%
  %
  \node[circle, minimum size=\tikzumlstateexitwidth, draw=\tikzumlstateexitcolor] (\tikzumlstateexitname) at (\tikzumlStateExitPos) {};%
  \draw[draw=\tikzumlstateexitcolor] (\tikzumlstateexitname.north east) -- (\tikzumlstateexitname.south west) (\tikzumlstateexitname.north west) -- (\tikzumlstateexitname.south east);
  %
  % add to fit
  \ifnum\c@tikzumlStateLevel>0%
    \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
    \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstateexitname)}%
    \stepcounter{tikzumlStateSubStateNum}%
  \fi%
  \stepcounter{tikzumlStateExitNum}%
}%

\newcommand{\umlstateend}[1][]{%
  \pgfkeys{/tikzuml/stateend/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=5ex,%
           name/.initial=stateend-\thetikzumlStateEndNum, color/.initial=\tikzumldrawcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlstateend, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/stateend/.cd, #1}%
  \pgfkeys{/tikzuml/stateend/.cd, x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstateendwidth,%
                                       name/.get=\tikzumlstateendname, color/.get=\tikzumlstateendcolor}%
  %  
  \def\tikzumlStateEndPos{\posx,\posy}%
  %
  \node[circle, minimum size=\tikzumlstateendwidth] (\tikzumlstateendname) at (\tikzumlStateEndPos) {};%
  \draw[draw=\tikzumlstateendcolor] (\tikzumlstateendname.north east) -- (\tikzumlstateendname.south west) (\tikzumlstateendname.north west) -- (\tikzumlstateendname.south east);
  %
  % add to fit
  \ifnum\c@tikzumlStateLevel>0%
    \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
    \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstateendname)}%
    \stepcounter{tikzumlStateSubStateNum}%
  \fi%
  \stepcounter{tikzumlStateEndNum}%
}%

\newcommand{\picturedhistory}[1]{%
  \begin{tikzpicture}[#1]
  \draw[thick] (-0.1cm,-0.15cm) -- (-0.1cm,0.15cm)
               (-0.1cm,0) -- (0.1cm,0)
               (0.1cm,-0.15cm) -- (0.1cm,0.15cm);
  \end{tikzpicture}
}%

\newcommand{\umlstatehistory}[1][]{%
  \pgfkeys{/tikzuml/statehistory/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=5ex,%
           name/.initial=statehistory-\thetikzumlStateHistoryNum,%
           color/.initial=\tikzumldrawcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlstatehistory, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/statehistory/.cd, #1}%
  \pgfkeys{/tikzuml/statehistory/.cd, x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstatehistorywidth,%
                                       name/.get=\tikzumlstatehistoryname, color/.get=\tikzumlstatehistorycolor}%
  %
  \def\tikzumlStateHistoryPos{\posx,\posy}%
  %
  \node[circle, minimum size=\tikzumlstatehistorywidth, draw=\tikzumlstatehistorycolor] (\tikzumlstatehistoryname) at (\tikzumlStateHistoryPos) {\picturedhistory{draw=\tikzumlstatehistorycolor}};%
  %
  % add to fit
  \ifnum\c@tikzumlStateLevel>0%
    \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
    \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstatehistoryname)}%
    \stepcounter{tikzumlStateSubStateNum}%
  \fi%
  \stepcounter{tikzumlStateHistoryNum}%
}%

\newcommand{\pictureddeephistory}[1]{%
  \begin{tikzpicture}[#1]
  \draw[thick] (-0.1cm,-0.15cm) -- (-0.1cm,0.15cm)
               (-0.1cm,0) -- (0.1cm,0)
               (0.1cm,-0.15cm) -- (0.1cm,0.15cm)
               (0.23cm,0.19cm) -- (0.23cm,0.11cm)
               (0.20cm,0.17cm) -- (0.26cm,0.13cm)
               (0.20cm,0.13cm) -- (0.26cm,0.17cm);
  \end{tikzpicture}
}%

\newcommand{\umlstatedeephistory}[1][]{%
  \pgfkeys{/tikzuml/statedeephistory/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=5ex,%
           name/.initial=statedeephistory-\thetikzumlStateDeepHistoryNum,%
           color/.initial=\tikzumldrawcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlstatedeephistory, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/statedeephistory/.cd, #1}%
  \pgfkeys{/tikzuml/statedeephistory/.cd, x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstatedeephistorywidth,%
                                       name/.get=\tikzumlstatedeephistoryname, color/.get=\tikzumlstatedeephistorycolor}%
  %  
  \def\tikzumlStateDeepHistoryPos{\posx,\posy}%
  %
  \node[circle, minimum size=\tikzumlstatedeephistorywidth, draw=\tikzumlstatedeephistorycolor] (\tikzumlstatedeephistoryname) at (\tikzumlStateDeepHistoryPos) {\pictureddeephistory{draw=\tikzumlstatedeephistorycolor}};%
  %
  % add to fit
  \ifnum\c@tikzumlStateLevel>0%
    \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
    \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstatedeephistoryname)}%
    \stepcounter{tikzumlStateSubStateNum}%
  \fi%
  \stepcounter{tikzumlStateDeepHistoryNum}%
}%

% define a uml state
% args : name of the state
%         content of the state
% optional args : x,y coordinates of the state
%                 width of the state node
\newenvironment{umlstate}[2][]{%
  \ifnum\thetikzumlStateLevel>0%
    \let\tikzumlState@nameold\tikzumlState@fitname%
    \let\tikzumlState@parentold\tikzumlState@parent%
    \edef\tikzumlState@parent{\tikzumlState@parentold @@\tikzumlState@nameold}%
  \else%
    \def\tikzumlState@parent{}%
  \fi%
  
  \stepcounter{tikzumlStateLevel}%
  
  \pgfkeys{/tikzuml/state/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=8ex, type/.initial=class,%
           name/.initial={},%
           entry/.initial={}, do/.initial={}, exit/.initial={},%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillstatecolor,%
           text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlstate, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/state/.cd, #1}%
  \pgfkeys{/tikzuml/state/.cd,%
           x/.get=\tikzumlstateX, y/.get=\tikzumlstateY, width/.get=\umlstateMinimumWidth,%
           type/.get=\umlstateType, name/.get=\umlstateName,%
           entry/.get=\umlstateentry, do/.get=\umlstatedo, exit/.get=\umlstateexit,%
           draw/.get=\tikzumlstatedraw, fill/.get=\tikzumlstatefill,%
           text/.get=\tikzumlstatetext}%
  %
  \ifthenelse{\equal{\umlstateName}{}}{%
    \edef\tikzumlState@name{#2}%
  }{%
    \edef\tikzumlState@name{\umlstateName}%
  }%
  %
  \begingroup%
    \def\_{@}\edef\x{\endgroup%
      \def\noexpand\tikzumlState@fitname{\tikzumlState@name}}\x%
  %
  \let\tikzumlState@nodeNameold\tikzumlState@nodeName%
  \def\tikzumlState@caption{#2}%
  % 
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlState@nodeName{\tikzumlState@name}}\x%
  %
  \expandafter\gdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{}%
  %
  \setcounter{tikzumlStateSubStateNum}{0}%
  \setcounter{tikzumlStateText}{0}%
  %
  \def\tikzumlStateText{tikzumlEmpty}%
  \begin{scope}[xshift=\tikzumlstateX cm, yshift=\tikzumlstateY cm]%
}{%
  %  
  \def\tikzumlstaterootlabel{\phantom{\tikzumlState@nodeName}}%
  %
  \def\tikzumlstaterootinnerysep{0.5ex}%
  \def\tikzumlstatebodyinnerysep{2ex}%
  %
  \ifthenelse{\equal{\umlstateentry}{}}{}{%
    \def\tikzumlStateText{entry/\umlstateentry}%
    \setcounter{tikzumlStateText}{1}%
    \ifnum\c@tikzumlStateSubStateNum=0%
      \def\tikzumlstatebodyinnerysep{0}%
      \def\tikzumlstaterootinnerysep{0}%
    \fi%
  }%
  \ifthenelse{\equal{\umlstatedo}{}}{}{%
    \ifnum\c@tikzumlStateText=0%
      \def\tikzumlStateText{do/\umlstatedo}%
    \else%
      \let\tikzumlStateTextOld\tikzumlStateText%
      \def\tikzumlStateText{\tikzumlStateTextOld \\ do/\umlstatedo}%
    \fi%
    \setcounter{tikzumlStateText}{1}%
    \ifnum\c@tikzumlStateSubStateNum=0%
      \def\tikzumlstatebodyinnerysep{0}%
      \def\tikzumlstaterootinnerysep{0}%
    \fi%
  }%
  \ifthenelse{\equal{\umlstateexit}{}}{}{%
    \ifnum\c@tikzumlStateText=0%
      \def\tikzumlStateText{exit/\umlstateexit}%
    \else%
      \let\tikzumlStateTextOld\tikzumlStateText%
      \def\tikzumlStateText{\tikzumlStateTextOld \\ exit/\umlstateexit}%
    \fi%
    \setcounter{tikzumlStateText}{1}%
    \ifnum\c@tikzumlStateSubStateNum=0%
      \def\tikzumlstatebodyinnerysep{0}%
      \def\tikzumlstaterootinnerysep{0}%
    \fi%
  }%
  %
  \addtocounter{tikzumlStateLevel}{-1}%
  \begin{pgfonlayer}{state\thetikzumlStateLevel}%
  %
  % if contains nothing, one define a fictive node to enable the fit option
  \ifnum\c@tikzumlStateSubStateNum=0%
    \node[inner ysep=\tikzumlstaterootinnerysep, minimum width=\umlstateMinimumWidth] (\tikzumlState@nodeName-root) at (0,0) {\tikzumlstaterootlabel};%
    \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{(\tikzumlState@nodeName-root)}%
  \fi%
  %
  \ifnum\c@tikzumlStateLevel>0%
    \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent\endcsname}%
    \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent\endcsname{\tikzumlStateFitTmp (\tikzumlState@nodeName-body) (\tikzumlState@nodeName-caption)}%
    \stepcounter{tikzumlStateSubStateNum}%
  \fi%
  %
  \node[inner xsep=2ex, inner ysep=\tikzumlstatebodyinnerysep, fit = \csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname] (\tikzumlState@nodeName-body) {};%
  \def\tikzumlState@orig{body}%
  \ifnum\c@tikzumlStateText=1%
    \node[above=0] (\tikzumlState@nodeName-texttmp) at (\tikzumlState@nodeName-\tikzumlState@orig.north) {\begin{tabular}{l}\tikzumlStateText \end{tabular}};%
    \def\tikzumlState@orig{texttmp}%
  \fi%
  \node[above] (\tikzumlState@nodeName-captiontmp) at (\tikzumlState@nodeName-\tikzumlState@orig.north) {\tikzumlState@caption};%
  \node[rounded corners, draw=\tikzumlstatedraw, fill=\tikzumlstatefill, name=\tikzumlState@nodeName, fit=(\tikzumlState@nodeName-body) (\tikzumlState@nodeName-captiontmp)] {};%
  \ifnum\c@tikzumlStateText=1%
    \node (\tikzumlState@nodeName-text) at (\tikzumlState@nodeName-texttmp) {\begin{tabular}{l}\tikzumlStateText \end{tabular}};%
  \fi%
  \node (\tikzumlState@nodeName-caption) at (\tikzumlState@nodeName-captiontmp) {\tikzumlState@caption};%
  \draw (\tikzumlState@nodeName-caption.south -| \tikzumlState@nodeName.north west) -- (\tikzumlState@nodeName-caption.south -| \tikzumlState@nodeName.north east);%
  \end{pgfonlayer}%
  \end{scope}%
}%

% shortcut for empty state
\newcommand{\umlbasicstate}[2][]{\begin{umlstate}[#1]{#2} \end{umlstate}}%

% command to add text in a state
\newcommand{\umlstatetext}[1]{%
  \def\tikzumlStateText{#1}%
  \setcounter{tikzumlStateText}{1}%
}%

% shortcuts for state transitions macros
\newcommand{\umltrans}[3][]{%
  \ifthenelse{\equal{#2}{#3}}{%
    \umlrelation[style={tikzuml transition style}, recursive mode=transition, #1]{#2}{#3}%
  }{%
    \umlrelation[style={tikzuml transition style}, #1]{#2}{#3}%
  }%
}%
\newcommand{\umlHVtrans}[3][]{\umlHVrelation[style={tikzuml transition style}, #1]{#2}{#3}}%
\newcommand{\umlVHtrans}[3][]{\umlVHrelation[style={tikzuml transition style}, #1]{#2}{#3}}%
\newcommand{\umlVHVtrans}[3][]{\umlVHVrelation[style={tikzuml transition style}, #1]{#2}{#3}}%
\newcommand{\umlHVHtrans}[3][]{\umlHVHrelation[style={tikzuml transition style}, #1]{#2}{#3}}%
\newcommand{\umlCNtrans}[4][]{\umlCNrelation[style={tikzuml transition style}, #1]{#2}{#3}{#4}}%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                     sequence diagrams                   %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\tikzstyle{tikzuml synchron-msg style}=[color=\tikzumldrawcolor, -triangle 45]%
\tikzstyle{tikzuml asynchron-msg style}=[color=\tikzumldrawcolor, -angle 45]%
\tikzstyle{tikzuml return-msg style}=[color=\tikzumldrawcolor, dashed, -angle 45]%
\tikzstyle{tikzuml call return style}=[color=\tikzumldrawcolor, dashed, -angle 45]%
\tikzstyle{tikzuml activity style}=[inner xsep=1ex, inner ysep=1ex]%

\newcounter{tikzumlObjectNum}
\newcounter{tikzumlCallLevel}
\newcounter{tikzumlCallNum}
\newcounter{tikzumlFragmentLevel}
\newcounter{tikzumlFragmentLevelNum}
\newcounter{tikzumlFragmentNum}
\newcounter{tikzumlFragmentPartNum}
\newcounter{tikzumlCallStartFragmentNum}
\newcounter{tikzumlCallEndFragmentNum}

% define a sequence diagram
% 
\newenvironment{umlseqdiag}{%
  \gdef\tikzumlInCreateCall{0}%
  \setcounter{tikzumlObjectNum}{0}%
  \setcounter{tikzumlCallLevel}{0}%
  \setcounter{tikzumlCallNum}{0}%
  \setcounter{tikzumlFragmentLevel}{0}%
  \setcounter{tikzumlFragmentLevelNum}{0}%
  \setcounter{tikzumlFragmentNum}{0}%
  \setcounter{tikzumlFragmentPartNum}{0}%
  \setcounter{tikzumlCallStartFragmentNum}{0}%
  \setcounter{tikzumlCallEndFragmentNum}{0}%
  %
  \ifx \@umlactor \@empty
    \newcommand{\umlactor}[2][]{%
      \pgfkeys{/tikzuml/actorobj/.cd,%
               .unknown/.code={%
                 \let\keyname=\pgfkeyscurrentname%
                 \ifthenelse{\equal{\keyname}{stereo}}{%
                   \errmessage{TIKZUML ERROR : in umlactor, forbidden option stereo}%
                 }{}%
               }}%
      %
      \pgfkeys{/tikzuml/actorobj/.cd, ##1}%
      \umlobject[stereo=actor, ##1]{##2}%
    }%
  \else%
    \renewcommand{\umlactor}[2][]{
      \pgfkeys{/tikzuml/actorobj/.cd,%
               .unknown/.code={%
                 \let\keyname=\pgfkeyscurrentname%
                 \ifthenelse{\equal{\keyname}{stereo}}{%
                   \errmessage{TIKZUML ERROR : in umlactor, forbidden option stereo}%
                 }{}%
               }}%
      %
      \pgfkeys{/tikzuml/actorobj/.cd, ##1}%
      \umlobject[stereo=actor, ##1]{##2}%
    }%
  \fi%
  \begin{scope}[font=\tikzumlfont]%
}{%
  % draw lifelines of each object
  \begin{pgfonlayer}{lifelines}%
  \foreach \id in \tikzumlIdList {%
    \draw (\csname tikzumlLastChild@\id \endcsname)+(0,-2.5ex) node[inner sep=0, name=end-\id] {};%
    \draw[dotted] (\id) -- (end-\id);%
  }%
  \end{pgfonlayer}%
  \end{scope}%
}%

% define the actor symbol
% optional : global tikzpicture styles
\newcommand{\pictureddatabase}[1]{%
  \pgfkeys{/tikzuml/database/.cd, scale/.initial=1, .unknown/.code={}}%
  \pgfkeys{/tikzuml/database/.cd,#1}%
  \pgfkeys{/tikzuml/database/.cd, scale/.get=\tikzumldatabasescale}%
  %
  \begin{tikzpicture}[#1]
  \node[fill, draw, ellipse, minimum width=\tikzumldatabasescale*4ex, minimum height=\tikzumldatabasescale*2ex, inner sep=0] (bottom) at (0,-2ex) {};
  \node[fill, draw, ellipse, minimum width=\tikzumldatabasescale*4ex, minimum height=\tikzumldatabasescale*2ex, inner sep=0] (top) at (0,4ex) {};
  \fill (bottom.west) rectangle (top.east);
  \begin{scope}
  \clip (-3.5ex,-0.5ex) rectangle (3.5ex,2.5ex);
  \node[draw, dashed, ellipse, minimum width=\tikzumldatabasescale*4ex, minimum height=\tikzumldatabasescale*2ex, inner sep=0] (bottom2) at (0,-2ex) {};
  \end{scope}
  \node[draw, ellipse, minimum width=\tikzumldatabasescale*4ex, minimum height=\tikzumldatabasescale*2ex, inner sep=0] (top2) at (0,4ex) {};
  \draw (bottom.west) -- (top.west) (bottom.east) -- (top.east);
  \end{tikzpicture}
}%

% define the actor symbol
% optional : global tikzpicture styles
\newcommand{\picturedentity}[1]{%
  \pgfkeys{/tikzuml/entity/.cd, scale/.initial=1, .unknown/.code={}}%
  \pgfkeys{/tikzuml/entity/.cd,#1}%
  \pgfkeys{/tikzuml/entity/.cd, scale/.get=\tikzumlentityscale}%
  %
  \begin{tikzpicture}[#1]%
  \node[fill, draw, circle, inner sep=0, minimum size=\tikzumlentityscale*5ex] (center) at (0,0) {};%
  \draw (center.south) node[coordinate, name=bottom] {};%
  \draw (bottom)+(-2ex,0) node[coordinate, name=bottom-left] {};%
  \draw (bottom)+(2ex,0) node[coordinate, name=bottom-right] {};%
  \draw (center) -- (bottom);%
  \draw (bottom-left) -- (bottom-right);%
  \end{tikzpicture}%
}%

% define the actor symbol
% optional : global tikzpicture styles
\newcommand{\picturedboundary}[1]{%
  \pgfkeys{/tikzuml/boundary/.cd, scale/.initial=1, .unknown/.code={}}%
  \pgfkeys{/tikzuml/boundary/.cd,#1}%
  \pgfkeys{/tikzuml/boundary/.cd, scale/.get=\tikzumlboundaryscale}%
  %
  \begin{tikzpicture}[#1]
  \node[fill, draw, circle, inner sep=0, minimum size=\tikzumlboundaryscale*5ex] (center) at (0,0) {};
  \draw (center.west)+(-0.8ex,0) node[coordinate, name=left] {};
  \draw (left)+(0,0.2ex) node[coordinate, name=left-top] {};
  \draw (left)+(0,-0.2ex) node[coordinate, name=left-bottom] {};
  \draw (center) -- (left);
  \draw (left-top) -- (left-bottom);
  \end{tikzpicture}
}%

% define the actor symbol
% optional : global tikzpicture styles
\newcommand{\picturedcontrol}[1]{%
  \pgfkeys{/tikzuml/control/.cd, scale/.initial=1, .unknown/.code={}}%
  \pgfkeys{/tikzuml/control/.cd,#1}%
  \pgfkeys{/tikzuml/control/.cd, scale/.get=\tikzumlcontrolscale}%
  %
  \begin{tikzpicture}[#1, decoration={markings, mark=at position 0.25 with {\arrow{>}}}]
  \node[fill, draw, circle, inner sep=0, minimum size=\tikzumlcontrolscale*5ex, postaction={decorate}] (center) at (0,0) {};
  \end{tikzpicture}
}% 

% define a uml object for a sequence diagram
% args : name of the object
% optional : x, y coordinates of the object
%            stereotype of the object (object, actor, database, boundary, control, entity, multiobject)
%            class of the object
%            draw, fill, text colors
\newcommand{\umlobject}[2][]{
  \stepcounter{tikzumlObjectNum}%
  %
  \edef\tikzumlobject@ddot{:}%
  \pgfkeys{/tikzuml/obj/.cd,%
           x/.initial={tikzumlEmpty}, y/.initial=0, stereo/.initial=object,%
           class/.initial={}, scale/.initial=1,%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillobjectcolor,%
           text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{no ddots}}{%
               \edef\tikzumlobject@ddot{}%
             }{%
               \errmessage{TIKZUML ERROR : in umlobj, invalid option \keyname}%
             }%
           }}%
  \pgfkeys{/tikzuml/obj/.cd, #1}%
  \pgfkeys{/tikzuml/obj/.cd,%
           x/.get=\tikzumlobjectX, y/.get=\tikzumlobjectY,%
           stereo/.get=\tikzumlobjectstereo, class/.get=\tikzumlobjectclass,%
           scale/.get=\tikzumlobjectscale,%
           draw/.get=\tikzumlobjectdraw, fill/.get=\tikzumlobjectfill,%
           text/.get=\tikzumlobjecttext}%
  %
  \ifthenelse{\equal{\tikzumlobjectX}{tikzumlEmpty}}{%
    \pgfmathsetmacro{\tikzumlobjectX}{4*(\thetikzumlObjectNum-1)}%
  }{}%
  %
  \def\tikzumlObjectName{#2}%
  \expandafter\xdef\csname tikzumlLastChild@\tikzumlObjectName \endcsname{\tikzumlObjectName}%
  %
  \ifnum\thetikzumlObjectNum=1%
    \xdef\tikzumlIdList{\tikzumlObjectName}%
  \else%
    \let\tikzumlIdListOld\tikzumlIdList%
    \xdef\tikzumlIdList{\tikzumlIdListOld,\tikzumlObjectName}%
  \fi%
  %
  \tikzstyle{tikzuml object box style}=[rectangle, text=\tikzumlobjecttext, font=\tikzumlfont]%
  %
  \ifthenelse{\equal{\tikzumlobjectstereo}{object}}{%
    \tikzstyle{tikzuml object box style}+=[draw=\tikzumlobjectdraw, fill=\tikzumlobjectfill]%
  }{%
    \ifthenelse{\equal{\tikzumlobjectstereo}{multi}}{%
      \tikzstyle{tikzuml object box style}+=[fill=\tikzumlobjectfill]%
    }{}%
  }%
  %
  \ifnum\tikzumlInCreateCall=1%
    \draw (\tikzumlCreateCallObjectSrc -| \tikzumlobjectX,0) node[tikzuml object box style] (\tikzumlObjectName) {\tikzumlObjectName\tikzumlobject@ddot\tikzumlobjectclass};%
  \else%
    \node[tikzuml object box style] (\tikzumlObjectName) at (\tikzumlobjectX,\tikzumlobjectY) {\tikzumlObjectName\tikzumlobject@ddot\tikzumlobjectclass};%
  \fi%
  %
  \ifthenelse{\equal{\tikzumlobjectstereo}{multi}}{%
    \draw (\tikzumlObjectName.north east)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-tr, coordinate] {};
    \draw (\tikzumlObjectName.north west)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-tl, coordinate] {};
    \draw (\tikzumlObjectName.south east)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-br, coordinate] {};
    \draw (\tikzumlObjectName-tr)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-ttr, coordinate] {};
    \draw (\tikzumlObjectName-tl)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-ttl, coordinate] {};
    \draw (\tikzumlObjectName-br)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-tbr, coordinate] {};
    \fill[fill=\tikzumlobjectfill] (\tikzumlObjectName-ttl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-ttl) -- (\tikzumlObjectName-ttr) -- (\tikzumlObjectName-tbr) -- (\tikzumlObjectName-tbr -| \tikzumlObjectName.east) -- (\tikzumlObjectName.north east) -- (\tikzumlObjectName-ttl |- \tikzumlObjectName.north);
    \draw[draw=\tikzumlobjectdraw] (\tikzumlObjectName-ttl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-ttl) -- (\tikzumlObjectName-ttr) -- (\tikzumlObjectName-tbr) -- (\tikzumlObjectName-tbr -| \tikzumlObjectName.east);
    \fill[fill=\tikzumlobjectfill] (\tikzumlObjectName-tl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-tl) -- (\tikzumlObjectName-tr) -- (\tikzumlObjectName-br) -- (\tikzumlObjectName-br -| \tikzumlObjectName.east) -- (\tikzumlObjectName.north east) -- (\tikzumlObjectName-tl |- \tikzumlObjectName.north);
    \draw[draw=\tikzumlobjectdraw] (\tikzumlObjectName-tl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-tl) -- (\tikzumlObjectName-tr) -- (\tikzumlObjectName-br) -- (\tikzumlObjectName-br -| \tikzumlObjectName.east);
    \draw[draw=\tikzumlobjectdraw] (\tikzumlObjectName.north west) rectangle (\tikzumlObjectName.south east);
  }{%
    \ifthenelse{\equal{\tikzumlobjectstereo}{object}}{}{%
      \node[above=1ex, name=\tikzumlObjectName-picture] at (\tikzumlObjectName) {\csname pictured\tikzumlobjectstereo \endcsname{draw=\tikzumlobjectdraw, fill=\tikzumlobjectfill, scale=\tikzumlobjectscale}};
    }%
  }%
}

% shortcuts for objects
\newcommand{\umlbasicobject}[2][]{%
  \pgfkeys{/tikzuml/basicobj/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{no ddots}}{%
               \errmessage{TIKZUML ERROR : in umlbasicobject, forbidden option no ddots}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/basicobj/.cd, #1}%
  \umlobject[no ddots, #1]{#2}%
}%

\newcommand{\umldatabase}[2][]{%
  \pgfkeys{/tikzuml/databaseobj/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umldatabase, forbidden option stereo}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/databaseobj/.cd, #1}%
  \umlobject[stereo=database, #1]{#2}%
}%
\newcommand{\umlentity}[2][]{%
  \pgfkeys{/tikzuml/entityobj/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlentity, forbidden option stereo}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/entityobj/.cd, #1}%
  \umlobject[stereo=entity, #1]{#2}%
}%
\newcommand{\umlcontrol}[2][]{%
  \pgfkeys{/tikzuml/controlobj/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlcontrol, forbidden option stereo}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/controlobj/.cd, #1}%
  \umlobject[stereo=control, #1]{#2}%
}%
\newcommand{\umlboundary}[2][]{%
  \pgfkeys{/tikzuml/boundaryobj/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlboundary, forbidden option stereo}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/boundaryobj/.cd, #1}%
  \umlobject[stereo=boundary, #1]{#2}%
}%
\newcommand{\umlmulti}[2][]{%
  \pgfkeys{/tikzuml/multiobj/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlmulti, forbidden option stereo}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/multiobj/.cd, #1}%
  \umlobject[stereo=multi, #1]{#2}%
}%

\newlength{\tikzumlCall@xa}%
\newlength{\tikzumlCall@xb}%

% define a uml operation call for sequence diagrams
% args : call sender
%        call receiver
% optional : dt, time delay from precedent event end
%            name of the call
%            operation name and input args
%            return value
%            type of the call (synchron, asynchron)
%            draw, fill, text colors
%            time padding from call start and to call end
\newenvironment{umlcall}[3][]{%
  \stepcounter{tikzumlCallNum}%
  \def\tikzumlCallWithReturn{tikzumlFalse}%
  \edef\tikzumlCall@lastchildNum{\thetikzumlCallNum}% for testing presence of sub-calls
  \gdef\tikzumlCallBottom{0}%
  %
  \pgfkeys{/tikzuml/call/.cd,%
           dt/.initial={tikzumlEmpty}, name/.initial={call-\thetikzumlCallNum},%
           op/.initial={}, return/.initial={}, type/.initial=synchron,%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillcallcolor,%
           text/.initial=\tikzumltextcolor,%
           padding/.initial=2,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{with return}}{%
               \def\tikzumlCallWithReturn{tikzumlTrue}%
             }{%
               \errmessage{TIKZUML ERROR : in umlcall,  invalid option \keyname}%
             }%
           }}%
  \pgfkeys{/tikzuml/call/.cd, #1}%
  \pgfkeys{/tikzuml/call/.cd,%
           dt/.get=\tikzumlcallDT, name/.get=\tikzumlcallname, op/.get=\tikzumlcallop,%
           return/.get=\tikzumlcallreturn, type/.get=\tikzumlcalltype,%
           padding/.get=\tikzumlcallpadding,%
           draw/.get=\tikzumlcalldraw, fill/.get=\tikzumlcallfill,%
           text/.get=\tikzumlcalltext}%
  %
  \edef\tikzumlfillcall{\tikzumlcallfill}%
  \edef\tikzumldrawcall{\tikzumlcalldraw}%
  \edef\tikzumltextcall{\tikzumlcalltext}%
  \edef\tikzumltypecall{\tikzumlcalltype}%
  %
  \ifthenelse{\equal{\tikzumlcallDT}{tikzumlEmpty}}{%
    \ifnum\thetikzumlCallNum=1%
      \def\tikzumlcallDT{2}%
      \def\tikzumlcallSrc{2}%
    \else%
      \def\tikzumlcallDT{2}%
      \def\tikzumlcallSrc{1}%
    \fi%
  }{
    \def\tikzumlcallSrc{0}%
  }%
  %
  \let\tikzumlCallStartNodeNameold\tikzumlCallStartNodeName%
  \def\tikzumlCallStartNodeName{#2}%
  \let\tikzumlCallEndNodeNameold\tikzumlCallEndNodeName%
  \def\tikzumlCallEndNodeName{#3}%
  \def\tikzumlcallheight{\tikzumlcallpadding}%
  %
  % managing time delays from previous/parent fragments 
  \ifnum\thetikzumlCallStartFragmentNum>0%
    \let\tikzumlcallDTold\tikzumlcallDT%
    \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}%
    \edef\tikzumlcallDT{\pgfmathresult}%
    \addtocounter{tikzumlCallStartFragmentNum}{-1}
  \fi%
  \ifnum\thetikzumlCallEndFragmentNum>0%
    \let\tikzumlcallDTold\tikzumlcallDT%
    \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}%
    \edef\tikzumlcallDT{\pgfmathresult}%
    \addtocounter{tikzumlCallEndFragmentNum}{-1}
  \fi%
  \ifnum\thetikzumlFragmentPartNum>0%
    \let\tikzumlcallDTold\tikzumlcallDT%
    \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}%
    \edef\tikzumlcallDT{\pgfmathresult}%
  \fi%
  %
  % managing parent-child structure
  \ifnum\thetikzumlCallLevel>0%
    \let\tikzumlCall@nameold\tikzumlCall@name%
    \edef\tikzumlCall@name{\tikzumlcallname}%
    \let\tikzumlCall@parentold\tikzumlCall@parent%
    \edef\tikzumlCall@parent{\tikzumlCall@parentold @@\tikzumlCall@nameold}%
  \else%
    \edef\tikzumlCall@parent{}%
    \edef\tikzumlCall@parentold{}%
    \edef\tikzumlCall@nameold{}
    \edef\tikzumlCall@name{\tikzumlcallname}%
  \fi%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlCall@nodeName{\tikzumlCall@name}}\x%
  %
  \let\tikzumlCall@nodeNameold\tikzumlCall@nodeName%
  %
  \def\tikzumlcallstyle{tikzuml \tikzumlcalltype-msg style}%
  %
  % top node of activity period of call sender
  \begin{pgfonlayer}{connections}%
  \pgfmathparse{\tikzumlcallDT+\tikzumlcallSrc}%
  \draw (\csname tikzumlLastChild@\tikzumlCallStartNodeName \endcsname)+(0,-\pgfmathresult ex) node[coordinate, name=tikzumlTmpNode] {};%
  \node[tikzuml activity style] (st-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};%
  %
  % update last node drawn on sender lifeline
  \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallStartNodeName \endcsname{st-\tikzumlCall@nodeName}%
  %
  % top node of activity period of call receiver
  \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{%
    \draw (st-\tikzumlCall@nodeName)+(0,-0.75*\tikzumlcallpadding ex) node[coordinate, name=tikzumlTmpNode] {};%
    \node[tikzuml activity style] (et-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};%
  }{%
    \node[tikzuml activity style] (et-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- st-\tikzumlCall@nodeName) {};%
  }%
  %
  % update last node drawn on receiver lifeline
  \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallEndNodeName \endcsname{et-\tikzumlCall@nodeName}%
  \xdef\tikzumlCallBottomSrc{et-\tikzumlCall@nodeName}%
  \end{pgfonlayer}%
  %
  \stepcounter{tikzumlCallLevel}%
}{%
  \addtocounter{tikzumlCallLevel}{-1}%
  %
  % bottom nodes of activity periods of call sender and receiver
  \begin{pgfonlayer}{connections}%
  \ifnum\tikzumlCall@lastchildNum=\thetikzumlCallNum%
    %
    % this test occurs a bug with latex package preview
    \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{%
      \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlcallpadding ex) node[coordinate, name=tikzumlTmpNode] {};%
      \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};% 
      \draw (eb-\tikzumlCall@nodeName)+(0,-0.75*\tikzumlcallpadding ex) node[coordinate, name=tikzumlTmpNode] {};%
      \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};% 
    }{%
      \ifthenelse{\equal{\tikzumlcallreturn}{tikzumlEmpty}}{%
        \pgfmathsetmacro{\tikzumlcallpaddingd}{0.5*\tikzumlcallpadding}%
      }{%
        \pgfmathsetmacro{\tikzumlcallpaddingd}{1.2*\tikzumlcallpadding}%
      }%
      \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlcallpaddingd ex) node[coordinate, name=tikzumlTmpNode] {};%
      \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};%
      \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- eb-\tikzumlCall@nodeName) {};%
    }%
    \xdef\tikzumlCallBottomSrc{sb-\tikzumlCall@nodeName}%
  \else%
    %
    % managing time delays from previous/parent fragments
    \ifnum\thetikzumlCallStartFragmentNum>0%
      \let\tikzumlcallheightold\tikzumlcallpadding
      \pgfmathparse{\tikzumlcallheightold+0.5*\tikzumlFragment@paddingy}
      \edef\tikzumlcallheight{\pgfmathresult}
      \addtocounter{tikzumlCallStartFragmentNum}{-1}
    \fi%
    \ifnum\thetikzumlCallEndFragmentNum>0%
      \let\tikzumlcallheightold\tikzumlcallpadding
      \pgfmathparse{\tikzumlcallheightold+0.5*\tikzumlFragment@paddingy}
      \edef\tikzumlcallheight{\pgfmathresult}
      \addtocounter{tikzumlCallEndFragmentNum}{-1}
    \fi%
    %
    \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{%
      \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlcallheight ex) node[coordinate, name=tikzumlTmpNode] {};%
      \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};%
      \draw (eb-\tikzumlCall@nodeName)+(0,-0.75*\tikzumlcallpadding ex) node[coordinate, name=tikzumlTmpNode] {};%
      \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};%
    }{%
      \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlcallheight ex) node[coordinate, name=tikzumlTmpNode] {};%
      \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};%
      \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- eb-\tikzumlCall@nodeName) {};%
    }%
    %
    \xdef\tikzumlCallBottomSrc{sb-\tikzumlCall@nodeName}%
  \fi%
  \end{pgfonlayer}%
  %
  % draw activity periods
  \begin{pgfonlayer}{activity}%
  \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{%
    % draw root activity period only
    \ifnum\thetikzumlCallLevel=0%
      \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);%
    \else%
      % draw root activity from inner call
      \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeNameold}}{}{%
        \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);%
      }%
    \fi%
  }{%
    % draw root activity period
    \ifnum\thetikzumlCallLevel=0%
      \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);%
    \else%
      % draw root activity from inner call
      \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeNameold}}{}{%
        \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);%
      }%
    \fi%
    % draw receiver activity period
    \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (et-\tikzumlCall@nodeName.north west) rectangle (eb-\tikzumlCall@nodeName.south east);%
  }%
  \end{pgfonlayer}%
  \ifthenelse{\equal{\tikzumlfillcallcolor}{\tikzumlcallfill}}{}{%
    \fill[\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);%
    \draw[\tikzumldrawcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south west) (st-\tikzumlCall@nodeName.north east) rectangle (sb-\tikzumlCall@nodeName.south east);
  }%
  %
  % update last nodes drawn on sender and receiver lifelines
  \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallEndNodeName \endcsname{eb-\tikzumlCall@nodeName}%
  \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallStartNodeName \endcsname{sb-\tikzumlCall@nodeName}%
  %
  % draw call arrows
  \begin{pgfonlayer}{connections}%
  \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{%
    \draw[\tikzumlcallstyle, \tikzumldrawcall] (st-\tikzumlCall@nodeName.east) -- ++(2.5*\tikzumlcallpadding ex,0) %
                                                    -- ++(0,-0.75*\tikzumlcallpadding ex) %
                                                    node[font=\tikzumlfont, text=\tikzumltextcall, midway, right, name=\tikzumlCall@nodeName-op] {\tikzumlcallop} %
                                                    -- (et-\tikzumlCall@nodeName.east);%
    %
    % draw return arrow and update fit for parent fragment
    \ifthenelse{\equal{\tikzumltypecall}{synchron}}{%
      \ifthenelse{\NOT\equal{\tikzumlcallreturn}{}\OR\equal{\tikzumlCallWithReturn}{tikzumlTrue}}{%
        \ifnum\c@tikzumlFragmentLevel>0%
          \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
          \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op) (\tikzumlCall@nodeName-return)}%
        \fi%
        %
        \draw[tikzuml call return style, \tikzumldrawcall] (eb-\tikzumlCall@nodeName.east) -- ++(2.5*\tikzumlcallpadding ex,0) -- ++(0,-0.75*\tikzumlcallpadding ex) %
                                                  node[font=\tikzumlfont, text=\tikzumltextcall, midway, right, name=\tikzumlCall@nodeName-return] {\tikzumlcallreturn} %
                                                  -- (sb-\tikzumlCall@nodeName.east);%
     }{%
        \ifnum\c@tikzumlFragmentLevel>0%
          \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
          \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}%
        \fi%
}%
    }{%
      \ifnum\c@tikzumlFragmentLevel>0%
        \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
        \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}%
      \fi%
      %
    }%
  }{%
    % draw call arrows
    \pgfextractx{\tikzumlCall@xa}{\pgfpointanchor{\tikzumlCallStartNodeName}{center}}%
    \pgfextractx{\tikzumlCall@xb}{\pgfpointanchor{\tikzumlCallEndNodeName}{center}}%
    %
    \ifthenelse{\tikzumlCall@xb>\tikzumlCall@xa}{%
      \draw[\tikzumlcallstyle, \tikzumldrawcall] (st-\tikzumlCall@nodeName.east) -- (et-\tikzumlCall@nodeName.west) %
                                                    node[font=\tikzumlfont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-op] {\tikzumlcallop};%
    }{%
      \draw[\tikzumlcallstyle, \tikzumldrawcall] (st-\tikzumlCall@nodeName.west) -- (et-\tikzumlCall@nodeName.east) %
                                                    node[font=\tikzumlfont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-op] {\tikzumlcallop};%
    }%
    %
    % draw return arrow and update fit for parent fragment
    \ifthenelse{\equal{\tikzumltypecall}{synchron}}{%
      \ifthenelse{\NOT\equal{\tikzumlcallreturn}{}\OR\equal{\tikzumlCallWithReturn}{tikzumlTrue}}{%
        \ifnum\c@tikzumlFragmentLevel>0%
          \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
          \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op) (\tikzumlCall@nodeName-return)}%
        \fi%
        %
        \ifthenelse{\tikzumlCall@xb>\tikzumlCall@xa}{%
          \draw[tikzuml call return style, \tikzumldrawcall] (eb-\tikzumlCall@nodeName.west) -- (sb-\tikzumlCall@nodeName.east) %
                                       node[font=\tikzumlfont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-return] {\tikzumlcallreturn};%
        }{%
          \draw[tikzuml call return style, \tikzumldrawcall] (eb-\tikzumlCall@nodeName.east) -- (sb-\tikzumlCall@nodeName.west) %
                                       node[font=\tikzumlfont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-return] {\tikzumlcallreturn};%
        }%
      }{%
        \ifnum\c@tikzumlFragmentLevel>0%
          \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
          \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}%
        \fi%
      }%
    }{%
      \ifnum\c@tikzumlFragmentLevel>0%
        \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
        \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}%
      \fi%
    }%
  }%
  \end{pgfonlayer}%
}%

% alias for function self call
\newenvironment{umlcallself}[2][]{\begin{umlcall}[#1]{#2}{#2} }{\end{umlcall}}%

% define a combined fragment
% optional : name of fragment
%            type of fragment (opt, alt, break, loop, par, critical, ignore, consider, assert, neg, weak, strict, ref)
%            label of fragment (ex : condition for opt, iterator for loop, ...)
%            inner xsep and ysep (padding of the fragment box)
%            draw, fill, text colors
\newenvironment{umlfragment}[1][]{%

  % define a fragment separator
  % optional : label of the fragment part (ex : else for alt)
  \providecommand{\umlfpart}[1][]{%
    \stepcounter{tikzumlFragmentPartNum}%
    %
    \node[outer sep=0, inner xsep=\tikzumlfragmentxsep ex, inner ysep=\tikzumlfragmentysep ex, fit=\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname, name=\tikzumlFragment@name-Part-tmp] {};%
    \node[anchor=east, name=\tikzumlFragment@name-PartType-\thetikzumlFragmentPartNum] at (\tikzumlFragment@name-Part-tmp.north west |- \tikzumlCallBottomSrc) {\phantom{\tikzumlfragmenttype}};
    \draw (\tikzumlFragment@name-PartType-\thetikzumlFragmentPartNum.north west |- \tikzumlCallBottomSrc)+(0,-0.4*\tikzumlFragment@paddingy ex) node[name=\tikzumlFragment@name-PartWest-\thetikzumlFragmentPartNum] {};
    \draw (\tikzumlFragment@name-Part-tmp.north east |- \tikzumlCallBottomSrc)+(0,-0.4*\tikzumlFragment@paddingy ex) node[name=\tikzumlFragment@name-PartEast-\thetikzumlFragmentPartNum] {};
    \draw[dashed] (\tikzumlFragment@name-PartWest-\thetikzumlFragmentPartNum) -- (\tikzumlFragment@name-PartEast-\thetikzumlFragmentPartNum);
    \draw (\tikzumlFragment@name-PartType-\thetikzumlFragmentPartNum)+(0,-0.4*\tikzumlFragment@paddingy ex) node[name=tikzumlTmpNode] {\phantom{\tikzumlfragmenttype}};
    \node[anchor=north west] at (tikzumlTmpNode.south west) {[##1]};%
  }%
  
  \stepcounter{tikzumlFragmentNum}%
  %
  \pgfkeys{/tikzuml/fragment/.cd,%
           name/.initial={fragment@\alph{tikzumlFragmentNum}}, type/.initial=opt,%
           label/.initial={tikzumlEmpty},%
           inner xsep/.initial=1, inner ysep/.initial=1,%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillfragmentcolor,%
           text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlfragment, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/fragment/.cd, #1}%
  \pgfkeys{/tikzuml/fragment/.cd,%
           name/.get=\tikzumlfragmentname, type/.get=\tikzumlfragmenttype,%
           label/.get=\tikzumlfragmentlabel,%
           inner xsep/.get=\tikzumlfragmentxsep, inner ysep/.get=\tikzumlfragmentysep,%
           draw/.get=\tikzumlfragmentdraw, fill/.get=\tikzumlfragmentfill,%
           text/.get=\tikzumlfragmenttext}%
  %
  \ifthenelse{\equal{\tikzumlfragmentlabel}{tikzumlEmpty}}{%
    \def\tikzumlfragmentlabel{}%
  }{%
    \let\tikzumlfragmentlabelold\tikzumlfragmentlabel%
    \def\tikzumlfragmentlabel{[\tikzumlfragmentlabelold]}%
  }%
  
  %
  \ifnum\thetikzumlFragmentLevel>0%
    \let\tikzumlFragment@parentold\tikzumlFragment@parent%
    \let\tikzumlFragment@nameold\tikzumlFragment@name%
    \edef\tikzumlFragment@parent{\tikzumlFragment@nameold}%
  \else%
    \setcounter{tikzumlFragmentPartNum}{0}%
    \edef\tikzumlFragment@parent{}%
    \edef\tikzumlFragment@parentold{}%
    \edef\tikzumlFragment@nameold{}%
  \fi%
  %
  \edef\tikzumlFragment@name{\tikzumlfragmentname}%
  \expandafter\gdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{}%
  %
  \stepcounter{tikzumlFragmentLevel}%
  %
  \ifnum\thetikzumlCallLevel>0%
    \stepcounter{tikzumlCallStartFragmentNum}%
  \fi%
  %
  \pgfmathparse{6*\tikzumlfragmentysep}%
  \xdef\tikzumlFragment@paddingy{\pgfmathresult}%
  \if\c@tikzumlFragmentLevelNum=0%
    \setcounter{tikzumlFragmentLevelNum}{\thetikzumlFragmentLevel}%
  \fi%
  %
  % time delay adjustment for two consecutive fragments
  \ifnum\thetikzumlCallEndFragmentNum>0%
    \addtocounter{tikzumlCallEndFragmentNum}{-1}
  \fi%
}{%
  %
  \addtocounter{tikzumlFragmentLevel}{-1}%
  %
  \ifnum\thetikzumlFragmentLevel>0%
    \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@parent \endcsname}%
    \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@parent \endcsname{\tikzumlFragmentFitOld (\tikzumlFragment@name)}%
  \fi%
  %
  % draw working fragment box
  \begin{pgfonlayer}{fragment\thetikzumlFragmentLevel}%
  \node[outer sep=0, inner xsep=\tikzumlfragmentxsep ex, inner ysep=\tikzumlfragmentysep ex, fit=\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname, name=\tikzumlFragment@name-back] {};%
  \end{pgfonlayer}%
  %
  % draw type and label
  \node[text=\tikzumlfragmenttext, font=\tikzumlfont, anchor=north east, name=\tikzumlFragment@name-type] %
                                   at (\tikzumlFragment@name-back.north west) {\tikzumlfragmenttype};%
  \node[text=\tikzumlfragmenttext, font=\tikzumlfont, anchor=north west, name=\tikzumlFragment@name-label] %
                                   at (\tikzumlFragment@name-type.south west) {\tikzumlfragmentlabel};%
  %
  % draw final fragment box
  \begin{pgfonlayer}{fragment\thetikzumlFragmentLevel}%
  \node[draw=\tikzumlfragmentdraw, fill=\tikzumlfragmentfill, outer sep=0, inner sep=0, font=\tikzumlfont, fit=(\tikzumlFragment@name-back) (\tikzumlFragment@name-type) (\tikzumlFragment@name-label), name=\tikzumlFragment@name] {};%
  \end{pgfonlayer}%
  %
  \draw[draw=\tikzumlfragmentdraw] (\tikzumlFragment@name.north west) rectangle (\tikzumlFragment@name.south east);%
  \draw (\tikzumlFragment@name-type.south east)+(0,1ex) node[name=\tikzumlFragment@name-typetop, inner sep=0] {};%
  \draw (\tikzumlFragment@name-type.south east)+(-1ex,0) node[name=\tikzumlFragment@name-typeleft, inner sep=0] {};%
  \draw (\tikzumlFragment@name.north west) -| (\tikzumlFragment@name-typetop.center) -- (\tikzumlFragment@name-typeleft.center) -| (\tikzumlFragment@name.north west);%
  %
  \ifnum\thetikzumlCallLevel>0%
    \stepcounter{tikzumlCallEndFragmentNum}%
  \fi%
}%

% define a constructor call
% arg : call sender
%       name of constructed object
% optional : x coordinate of the new object
%            stereotype of the new object
%            class type of the new object
%            time delay from last event
%            name of the call
%            draw, fill, text colors
\newcommand{\umlcreatecall}[3][]{%
  \stepcounter{tikzumlCallNum}%
  \edef\tikzumlCall@lastchildNum{\thetikzumlCallNum}% for testing presence of sub-calls
  \gdef\tikzumlInCreateCall{1}%
  \pgfkeys{/tikzuml/createcall/.cd,%
           x/.initial={tikzumlEmpty}, stereo/.initial=object, class/.initial={},%
           dt/.initial=4, name/.initial={call-\thetikzumlCallNum},%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillcallcolor,%
           text/.initial=\tikzumltextcolor,%
           draw obj/.initial=\tikzumldrawcolor, fill obj/.initial=\tikzumlfillobjectcolor,%
           text obj/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlcreatecall, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/createcall/.cd, #1}%
  \pgfkeys{/tikzuml/createcall/.cd,%
           x/.get=\tikzumlcallX, stereo/.get=\tikzumlcallstereo,%
           class/.get=\tikzumlcallclass,%
           dt/.get=\tikzumlcallDT, name/.get=\tikzumlcallname,%
           draw/.get=\tikzumlcalldraw, fill/.get=\tikzumlcallfill,%
           text/.get=\tikzumlcalltext,%
           draw obj/.get=\tikzumlcallobjdraw, fill obj/.get=\tikzumlcallobjfill,%
           text obj/.get=\tikzumlcallobjtext}%
  %
  \def\tikzumlCreateCallSrc@name{#2}%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlCreateCallSrc@nodeName{\tikzumlCreateCallSrc@name}}\x%
  %
  % managing time delays from previous/parent fragments 
  \ifnum\thetikzumlCallStartFragmentNum>0%
    \let\tikzumlcallDTold\tikzumlcallDT%
    \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}%
    \edef\tikzumlcallDT{\pgfmathresult}%
    \addtocounter{tikzumlCallStartFragmentNum}{-1}
  \fi%
  \ifnum\thetikzumlCallEndFragmentNum>0%
    \let\tikzumlcallDTold\tikzumlcallDT%
    \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}%
    \edef\tikzumlcallDT{\pgfmathresult}%
    \addtocounter{tikzumlCallEndFragmentNum}{-1}
  \fi%
  \ifnum\thetikzumlFragmentPartNum>0%
    \let\tikzumlcallDTold\tikzumlcallDT%
    \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}%
    \edef\tikzumlcallDT{\pgfmathresult}%
  \fi%
  %
  % managing parent-child structure
  \ifnum\thetikzumlCallLevel>0%
    \let\tikzumlCall@nameold\tikzumlCall@name%
    \def\tikzumlCall@name{\tikzumlcallname}%
    \let\tikzumlCall@parentold\tikzumlCall@parent%
    \edef\tikzumlCall@parent{\tikzumlCall@parentold @@\tikzumlCall@nameold}%
  \else%
    \edef\tikzumlCall@parent{}%
    \edef\tikzumlCall@parentold{}%
    \edef\tikzumlCall@nameold{}
    \edef\tikzumlCall@name{\tikzumlcallname}%
  \fi%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlCreateCall@nodeName{\tikzumlCall@name}}\x%
  %
  \draw (\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname)+(0,-\tikzumlcallDT ex) node[name=st-\tikzumlCreateCall@nodeName, tikzuml activity style] {};%
  %
  \xdef\tikzumlCreateCallObjectSrc{st-\tikzumlCreateCall@nodeName}%
  %
  \umlobject[x=\tikzumlcallX, stereo=\tikzumlcallstereo, class=\tikzumlcallclass, draw=\tikzumlcallobjdraw, fill=\tikzumlcallobjfill, text=\tikzumlcallobjtext]{#3}%
  %
  \draw (\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname |- #3)+(0,-0.5*\tikzumlcallDT ex) node[name=sb-\tikzumlCreateCall@nodeName, tikzuml activity style] {};%
  %
  \expandafter\xdef\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname{sb-\tikzumlCreateCall@nodeName}%
  \xdef\tikzumlCallBottomSrc{sb-\tikzumlCreateCall@nodeName}%
  %
  \begin{pgfonlayer}{connections}%
  \draw[tikzuml synchron-msg style, \tikzumlcalldraw] (st-\tikzumlCreateCall@nodeName) -- (#3) node[midway, above, font=\tikzumlfont, text=\tikzumlcalltext, name=\tikzumlCreateCall@nodeName-op] {create};%
  \end{pgfonlayer}%
  %
  \ifnum\thetikzumlCallLevel=0%
    \begin{pgfonlayer}{activity}%
    \draw[draw=\tikzumlcalldraw, fill=\tikzumlcallfill] (st-\tikzumlCreateCall@nodeName.north west) rectangle (sb-\tikzumlCreateCall@nodeName.south east);%
    \end{pgfonlayer}%
  \fi%
  % add to fit fragment
  \ifnum\c@tikzumlFragmentLevel>0%
    \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
    \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCreateCall@nodeName) (sb-\tikzumlCreateCall@nodeName) (\tikzumlCreateCall@nodeName-op) (#3) }%
  \fi%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                     component diagrams                   %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\tikzstyle{tikzuml connector style}=[color=\tikzumldrawcolor, -]%

\newcounter{tikzumlComponentLevel}%
\newcounter{tikzumlComponentSubComponentNum}%
\newcounter{tikzumlConnectorNum}%
\setcounter{tikzumlConnectorNum}{1}%

\newcommand{\picturedcomponent}[1]{%
  \pgfkeys{/tikzuml/component/picture/.cd, scale/.initial=1, .unknown/.code={}}%
  \pgfkeys{/tikzuml/component/picture/.cd,#1}%
  \pgfkeys{/tikzuml/component/picture/.cd, scale/.get=\tikzumlcomponentscale}%
  \begin{tikzpicture}[#1]%
  \filldraw (0,0) rectangle (1ex,1.5ex);%
  \filldraw (-0.2ex,0.4ex) rectangle (0.2ex,0.6ex);%
  \filldraw (-0.2ex,0.9ex) rectangle (0.2ex,1.1ex);%
  \end{tikzpicture}%
}%

% define a uml component
% args : name of the component
%         content of the component
% optional args : x,y coordinates of the component
%                 width of the component node
\newenvironment{umlcomponent}[2][]{%
  \ifnum\thetikzumlComponentLevel>0%
    \let\tikzumlComponent@nameold\tikzumlComponent@fitname%
    \let\tikzumlComponent@parentold\tikzumlComponent@parent%
    \edef\tikzumlComponent@parent{\tikzumlComponent@parentold @@\tikzumlComponent@nameold}%
  \else%
    \def\tikzumlComponent@parent{}%
  \fi%
  %
  \stepcounter{tikzumlComponentLevel}%
  %
  \pgfkeys{/tikzuml/component/.cd,%
           x/.initial=0, y/.initial=0, width/.initial=8ex, name/.initial={},%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillcomponentcolor,%
           text/.initial=\tikzumltextcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlcomponent, invalid option \keyname}%
           }}%
  \pgfkeys{/tikzuml/component/.cd, #1}%
  \pgfkeys{/tikzuml/component/.cd,%
           x/.get=\tikzumlcomponentX, y/.get=\tikzumlcomponentY,%
           width/.get=\umlcomponentMinimumWidth, name/.get=\umlcomponentName,%
           draw/.get=\tikzumlcomponentdraw, fill/.get=\tikzumlcomponentfill,%
           text/.get=\tikzumlcomponenttext}%
  %
  \ifthenelse{\equal{\umlcomponentName}{}}{%
    \edef\tikzumlComponent@name{#2}%
  }{%
    \edef\tikzumlComponent@name{\umlcomponentName}%
  }%
  %
  \begingroup%
    \def\_{@}\edef\x{\endgroup%
      \def\noexpand\tikzumlComponent@fitname{\tikzumlComponent@name}}\x%
  %
  \let\tikzumlComponent@nodeNameold\tikzumlComponent@nodeName%
  \def\tikzumlComponent@caption{#2}%
  %  
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlComponent@nodeName{\tikzumlComponent@name}}\x%
  %
  \expandafter\gdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{}%
  %
  \setcounter{tikzumlComponentSubComponentNum}{0}%
  %
  \begin{scope}[xshift=\tikzumlcomponentX cm, yshift=\tikzumlcomponentY cm]%
}{%
  \addtocounter{tikzumlComponentLevel}{-1}%
  \begin{pgfonlayer}{component\thetikzumlComponentLevel}%
  %
  % if contains nothing, one define a fictive node to enable the fit option
  \ifnum\c@tikzumlComponentSubComponentNum=0%
    \node[inner ysep=0.5ex, minimum width=\umlcomponentMinimumWidth, font=\tikzumlfont] (\tikzumlComponent@nodeName-root) at (0,0) {\phantom{\tikzumlComponent@nodeName}};%
    \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{(\tikzumlComponent@nodeName-root)}%
  \fi%
  %
  \ifnum\c@tikzumlComponentLevel>0%
    \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent\endcsname}%
    \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent\endcsname{\tikzumlComponentFitTmp (\tikzumlComponent@nodeName-body) (\tikzumlComponent@nodeName-caption)}%
    \stepcounter{tikzumlComponentSubComponentNum}%
  \fi%
  %
  \node[inner sep=2ex, font=\tikzumlfont, fit = \csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname] (\tikzumlComponent@nodeName-body) {};%
  \node[above, font=\tikzumlfont] (\tikzumlComponent@nodeName-captiontmp) at (\tikzumlComponent@nodeName-body.north) {\tikzumlComponent@caption};%
  \node (\tikzumlComponent@nodeName-logotmp) at (\tikzumlComponent@nodeName-captiontmp.north -| \tikzumlComponent@nodeName-body.east) {\picturedcomponent{draw=\tikzumlcomponentdraw, fill=\tikzumlcomponentfill, font=\tikzumlfont} };%
  \node[draw=\tikzumlcomponentdraw, fill=\tikzumlcomponentfill, name=\tikzumlComponent@nodeName, fit=(\tikzumlComponent@nodeName-body) (\tikzumlComponent@nodeName-captiontmp)] {};%
  \node[font=\tikzumlfont] (\tikzumlComponent@nodeName-caption) at (\tikzumlComponent@nodeName-captiontmp) {\tikzumlComponent@caption};%
  \draw (\tikzumlComponent@nodeName-caption.north -| \tikzumlComponent@nodeName.east) node[font=\tikzumlfont, xshift=-1ex, below=-1ex, name=\tikzumlComponent@nodeName-logo] {\picturedcomponent{draw=\tikzumlcomponentdraw, fill=\tikzumlcomponentfill, font=\tikzumlfont} };%
  \draw (\tikzumlComponent@nodeName-caption.south -| \tikzumlComponent@nodeName.north west) -- (\tikzumlComponent@nodeName-caption.south -| \tikzumlComponent@nodeName.north east);%
  \coordinate (\tikzumlComponent@nodeName-west-port) at (\tikzumlComponent@nodeName.west);
  \coordinate (\tikzumlComponent@nodeName-east-port) at (\tikzumlComponent@nodeName.east);
  \coordinate (\tikzumlComponent@nodeName-south-port) at (\tikzumlComponent@nodeName.south);
  \coordinate (\tikzumlComponent@nodeName-north-port) at (\tikzumlComponent@nodeName.north);

  \end{pgfonlayer}%
  \end{scope}%
  %
  % add to fit
  \ifnum\c@tikzumlPackageLevel>0%
    \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}%
    \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlComponent@nodeName)}%
    \stepcounter{tikzumlPackageClassNum}%
  \fi%
}%

% shortcut for empty state
\newcommand{\umlbasiccomponent}[2][]{\begin{umlcomponent}[#1]{#2} \end{umlcomponent}}%

\newcommand{\umlrequiredinterface}[2][]{%
  \def\tikzumlInterfaceWithPort{tikzumlFalse}%
  \pgfkeys{/tikzuml/requiredinterfacerelation/.cd,%
           interface/.initial={}, distance/.initial=2.5cm,%
           width/.initial=1em, padding/.initial=1cm,%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillcomponentcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{with port}}{%
               \def\tikzumlInterfaceWithPort{tikzumlTrue}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/requiredinterfacerelation/.cd, #1}%
  \pgfkeys{/tikzuml/requiredinterfacerelation/.cd,%
           interface/.get=\tikzumlRequiredInterfaceLabel,%
           distance/.get=\tikzumlRequiredInterfaceDistance,%
           width/.get=\tikzumlRequiredInterfaceWidth,%
           padding/.get=\tikzumlRequiredInterfacePadding,%
           draw/.get=\tikzumlrequiredinterfacedraw,%
           fill/.get=\tikzumlrequiredinterfacefill,}%
  %
  \edef\tikzumlRequiredInterface@name{#2}%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlRequiredInterface@nodeName{\tikzumlRequiredInterface@name}}\x%
  %
  \ifthenelse{\equal{\tikzumlInterfaceWithPort}{tikzumlTrue}}{%
    \node[inner sep=0.5*\tikzumlRequiredInterfaceWidth, rectangle, draw=\tikzumlrequiredinterfacedraw, fill=\tikzumlrequiredinterfacefill] (\tikzumlRequiredInterface@nodeName-east-port) at (\tikzumlRequiredInterface@nodeName.east) {};%
  }{%
    \node[inner sep=0] (\tikzumlRequiredInterface@nodeName-east-port) at (\tikzumlRequiredInterface@nodeName.east) {};%
  }%
  \begin{scope}%
  \draw (\tikzumlRequiredInterface@nodeName)+(\tikzumlRequiredInterfaceDistance,0) node[inner sep=0, text width=\tikzumlRequiredInterfaceWidth, circle, name=\tikzumlRequiredInterface@nodeName-east-interface-tmp] {};%
  \clip (\tikzumlRequiredInterface@nodeName-east-interface-tmp.north) rectangle (\tikzumlRequiredInterface@nodeName-east-interface-tmp.south -| \tikzumlRequiredInterface@nodeName-east-interface-tmp.west);%
  \node[inner sep=0, text width=\tikzumlRequiredInterfaceWidth, circle, draw=\tikzumlrequiredinterfacedraw] (\tikzumlRequiredInterface@nodeName-east-interface) at (\tikzumlRequiredInterface@nodeName-east-interface-tmp) {};%
  \end{scope}%
  \node[above] at (\tikzumlRequiredInterface@nodeName-east-interface.north) {\tikzumlRequiredInterfaceLabel};%
  %
  \umlrelation[style={tikzuml connector style}, #1]{\tikzumlRequiredInterface@nodeName-east-port}{\tikzumlRequiredInterface@nodeName-east-interface}%

  \draw (\tikzumlRequiredInterface@nodeName-east-interface)+(\tikzumlRequiredInterfacePadding,0) node[name=\tikzumlRequiredInterface@nodeName-east-padding] {};%

  % add to fit
  \ifnum\c@tikzumlComponentLevel>0%
        \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname}%
        \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlRequiredInterface@nodeName-east-padding) (\tikzumlRequiredInterface@nodeName-east-port) }%
  \fi%
}%

\newcommand{\umlprovidedinterface}[2][]{%
  \def\tikzumlInterfaceWithPort{tikzumlFalse}%
  \pgfkeys{/tikzuml/providedinterfacerelation/.cd,%
           interface/.initial={}, distance/.initial=3cm,%
           width/.initial=1em, padding/.initial=1cm,%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillcomponentcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{with port}}{%
               \def\tikzumlInterfaceWithPort{tikzumlTrue}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/providedinterfacerelation/.cd, #1}%
  \pgfkeys{/tikzuml/providedinterfacerelation/.cd,%
           interface/.get=\tikzumlProvidedInterfaceLabel,%
           distance/.get=\tikzumlProvidedInterfaceDistance,%
           padding/.get=\tikzumlProvidedInterfacePadding,%
           width/.get=\tikzumlProvidedInterfaceWidth,%
           draw/.get=\tikzumlprovidedinterfacedraw,%
           fill/.get=\tikzumlprovidedinterfacefill}%
  %
  \edef\tikzumlProvidedInterface@name{#2}%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlProvidedInterface@nodeName{\tikzumlProvidedInterface@name}}\x%
  %
  \ifthenelse{\equal{\tikzumlInterfaceWithPort}{tikzumlTrue}}{%
    \node[inner sep=0.5*\tikzumlProvidedInterfaceWidth, rectangle, draw=\tikzumlprovidedinterfacedraw, fill=\tikzumlprovidedinterfacefill] (\tikzumlProvidedInterface@nodeName-west-port) at (\tikzumlProvidedInterface@nodeName.west) {};%
  }{%
    \node[inner sep=0] (\tikzumlProvidedInterface@nodeName-west-port) at (\tikzumlProvidedInterface@nodeName.west) {};%
  }%
  \draw (\tikzumlProvidedInterface@nodeName)+(-\tikzumlProvidedInterfaceDistance,0) node[inner sep=0, text width=\tikzumlProvidedInterfaceWidth, circle, draw=\tikzumlprovidedinterfacedraw, fill=\tikzumlprovidedinterfacefill, name=\tikzumlProvidedInterface@nodeName-west-interface] {};%
  \node[above] at (\tikzumlProvidedInterface@nodeName-west-interface.north)
 {\tikzumlProvidedInterfaceLabel};%
  %
  \umlrelation[style={tikzuml connector style}, #1]{\tikzumlProvidedInterface@nodeName-west-port}{\tikzumlProvidedInterface@nodeName-west-interface}%

  \draw (\tikzumlProvidedInterface@nodeName-west-interface)+(-\tikzumlProvidedInterfacePadding,0) node[name=\tikzumlProvidedInterface@nodeName-west-padding] {};%
   % add to fit
  \ifnum\thetikzumlComponentLevel>0%
        \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname}%
        \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlProvidedInterface@nodeName-west-padding) (\tikzumlProvidedInterface@nodeName-west-port) }%
      \fi%
}%

\newlength{\tikzuml@AC@xa}%
\newlength{\tikzuml@AC@ya}%
\newlength{\tikzuml@AC@xb}%
\newlength{\tikzuml@AC@yb}%
\newlength{\tikzuml@AC@xi}%
\newlength{\tikzuml@AC@yi}%
\newlength{\tikzuml@AC@xic}%
\newlength{\tikzuml@AC@yic}%
\newlength{\tikzuml@AC@xio}%
\newlength{\tikzuml@AC@yio}%
\newlength{\tikzuml@AC@AB}%
\newlength{\tikzuml@AC@lambda}%
\newlength{\tikzuml@AC@xtrc}%
\newlength{\tikzuml@AC@ytrc}%
\newlength{\tikzuml@AC@xtlc}%
\newlength{\tikzuml@AC@ytlc}%
\newlength{\tikzuml@AC@xblc}%
\newlength{\tikzuml@AC@yblc}%
\newlength{\tikzuml@AC@xbrc}%
\newlength{\tikzuml@AC@ybrc}%
\newlength{\tikzuml@AC@middleArm}%

\newcommand{\umlassemblyconnectorsymbol}[2]{%
  \ifthenelse{\NOT\equal{\tikzumlAssemblyConnectorLabel}{}}{%
  \edef\tikzuml@ACStart@name{#1}%
  \edef\tikzuml@ACEnd@name{#2}%
  \edef\tikzuml@AC@width{\tikzumlAssemblyConnectorWidth}%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzuml@ACStart@nodeName{\tikzuml@ACStart@name}}\x%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzuml@ACEnd@nodeName{\tikzuml@ACEnd@name}}\x%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzuml@ACInterface@nodeName{\tikzumlAssemblyConnectorSymbolName}}\x%
  %
  \pgfextractx{\tikzuml@AC@xa}{\pgfpointanchor{\tikzuml@ACStart@nodeName}{\tikzumlAssemblyConnectorStartAnchor}}%
  \pgfextracty{\tikzuml@AC@ya}{\pgfpointanchor{\tikzuml@ACStart@nodeName}{\tikzumlAssemblyConnectorStartAnchor}}%
  \pgfextractx{\tikzuml@AC@xb}{\pgfpointanchor{\tikzuml@ACEnd@nodeName}{\tikzumlAssemblyConnectorEndAnchor}}%
  \pgfextracty{\tikzuml@AC@yb}{\pgfpointanchor{\tikzuml@ACEnd@nodeName}{\tikzumlAssemblyConnectorEndAnchor}}%
  \pgfmathsetlength{\tikzuml@AC@xi}{0.5*\tikzuml@AC@xa+0.5*\tikzuml@AC@xb}%
  \pgfmathsetlength{\tikzuml@AC@yi}{0.5*\tikzuml@AC@ya+0.5*\tikzuml@AC@yb}%
  \pgfmathsetlength{\tikzuml@AC@AB}{veclen(\tikzuml@AC@xa-\tikzuml@AC@xb,\tikzuml@AC@ya-\tikzuml@AC@yb)}%
  \pgfmathsetlength{\tikzuml@AC@lambda}{0.25*\tikzuml@AC@width/\tikzuml@AC@AB}%
  \pgfmathsetlength{\tikzuml@AC@xic}{\tikzuml@AC@xi-\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}%
  \pgfmathsetlength{\tikzuml@AC@yic}{\tikzuml@AC@yi-\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}%
  \pgfmathsetlength{\tikzuml@AC@xio}{\tikzuml@AC@xi+\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}%
  \pgfmathsetlength{\tikzuml@AC@yio}{\tikzuml@AC@yi+\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}%
  \node[inner sep=0.5*\tikzuml@AC@width] (\tikzuml@ACInterface@nodeName-interface) at (\tikzuml@AC@xi,\tikzuml@AC@yi) {};%
  \node[inner sep=0, text width=\tikzuml@AC@width, circle, draw=\tikzumlassemblyconnectordraw, fill=\tikzumlassemblyconnectorfill] (\tikzuml@ACInterface@nodeName-io) at (\tikzuml@AC@xio,\tikzuml@AC@yio) {};%
  \begin{scope}%
  \pgfmathsetlength{\tikzuml@AC@xtrc}{\tikzuml@AC@xic-2*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}%
  \pgfmathsetlength{\tikzuml@AC@ytrc}{\tikzuml@AC@yic+2*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}%
  \pgfmathsetlength{\tikzuml@AC@xbrc}{\tikzuml@AC@xic+2*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}%
  \pgfmathsetlength{\tikzuml@AC@ybrc}{\tikzuml@AC@yic-2*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}%
  \pgfmathsetlength{\tikzuml@AC@xtlc}{\tikzuml@AC@xic-3*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya+\tikzuml@AC@xb-\tikzuml@AC@xa)}%
  \pgfmathsetlength{\tikzuml@AC@ytlc}{\tikzuml@AC@yic+3*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa+\tikzuml@AC@ya-\tikzuml@AC@yb)}%
  \pgfmathsetlength{\tikzuml@AC@xblc}{\tikzuml@AC@xic+3*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya+\tikzuml@AC@xa-\tikzuml@AC@xb)}%
  \pgfmathsetlength{\tikzuml@AC@yblc}{\tikzuml@AC@yic-3*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa+\tikzuml@AC@yb-\tikzuml@AC@ya)}%
  \coordinate (\tikzuml@ACInterface@nodeName-trc) at (\tikzuml@AC@xtrc,\tikzuml@AC@ytrc);%
  \coordinate (\tikzuml@ACInterface@nodeName-brc) at (\tikzuml@AC@xbrc,\tikzuml@AC@ybrc);%
  \coordinate (\tikzuml@ACInterface@nodeName-tlc) at (\tikzuml@AC@xtlc,\tikzuml@AC@ytlc);%
  \coordinate (\tikzuml@ACInterface@nodeName-blc) at (\tikzuml@AC@xblc,\tikzuml@AC@yblc);%
  \clip (\tikzuml@ACInterface@nodeName-trc) --  (\tikzuml@ACInterface@nodeName-tlc) -- (\tikzuml@ACInterface@nodeName-blc) -- (\tikzuml@ACInterface@nodeName-brc) -- cycle;%
  \node[inner sep=0, text width=\tikzuml@AC@width, circle, draw=\tikzumlassemblyconnectordraw, fill=\tikzumlassemblyconnectorfill] (\tikzuml@ACInterface@nodeName-ic) at (\tikzuml@AC@xic,\tikzuml@AC@yic) {};%
  \end{scope}%
  \node[above, font=\tikzumlfont] at (\tikzuml@ACInterface@nodeName-interface.north)
 {\tikzumlAssemblyConnectorLabel};%
  }{}%
}%

\newcommand{\umlassemblyconnector}[3][]{%
  \def\tikzumlAssemblyConnectorWithPort{tikzumlFalse}%
  \def\tikzumlAssemblyConnectorFirstArm{tikzumlFalse}%
  \def\tikzumlAssemblyConnectorSecondArm{tikzumlFalse}%
  \def\tikzumlAssemblyConnectorMiddleArm{tikzumlFalse}%
  \def\tikzumlAssemblyConnectorLastArm{tikzumlFalse}%
  \pgfkeys{/tikzuml/assemblyconnectorrelation/.cd,%
           geometry/.initial=--, interface/.initial={},%
           arm1/.initial={auto}, arm2/.initial={auto},%
           name/.initial=connector-\thetikzumlConnectorNum, width/.initial=1em,%
           anchor1/.initial={}, anchor2/.initial={},%
           draw/.initial=\tikzumldrawcolor,%
           fill assembly connector/.initial=\tikzumlfillassemblyconnectorcolor,%
           fill port/.initial=\tikzumlfillportcolor,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{with port}}{%
               \def\tikzumlAssemblyConnectorWithPort{tikzumlTrue}%
             }{%
               \ifthenelse{\equal{\keyname}{first arm}}{%
                 \def\tikzumlAssemblyConnectorFirstArm{tikzumlTrue}%
               }{%
                 \ifthenelse{\equal{\keyname}{second arm}}{%
                   \def\tikzumlAssemblyConnectorSecondArm{tikzumlTrue}%
                 }{%
                   \ifthenelse{\equal{\keyname}{middle arm}}{%
                     \def\tikzumlAssemblyConnectorMiddleArm{tikzumlTrue}%
                   }{%
                     \ifthenelse{\equal{\keyname}{last arm}}{%
                       \def\tikzumlAssemblyConnectorLastArm{tikzumlTrue}%
                     }{%
                     }%
                   }%
                 }%
               }%
             }%
           }}%
  \pgfkeys{/tikzuml/assemblyconnectorrelation/.cd, #1}%
  \pgfkeys{/tikzuml/assemblyconnectorrelation/.cd,%
           geometry/.get=\tikzumlAssemblyConnectorGeometry,%
           name/.get=\tikzumlAssemblyConnectorName,%
           interface/.get=\tikzumlAssemblyConnectorLabel,%
           width/.get=\tikzumlAssemblyConnectorWidth,%
           arm1/.get=\tikzumlAssemblyConnectorStartArm,%
           arm2/.get=\tikzumlAssemblyConnectorEndArm,%
           anchor1/.get=\umlAssemblyConnectorStartAnchor,%
           anchor2/.get=\umlAssemblyConnectorEndAnchor,%
           draw/.get=\tikzumlassemblyconnectordraw,%
           fill assembly connector/.get=\tikzumlassemblyconnectorfill,%
           fill port/.get=\tikzumlassemblyconnectorportfill}%
  %
  \edef\tikzumlAssemblyConnectorStart@name{#2}%
  \edef\tikzumlAssemblyConnectorEnd@name{#3}%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlAssemblyConnectorStart@nodeName{\tikzumlAssemblyConnectorStart@name}}\x%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlAssemblyConnectorEnd@nodeName{\tikzumlAssemblyConnectorEnd@name}}\x%
  %
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlAssemblyConnectorLabel@nodeName{\tikzumlAssemblyConnectorLabel}}\x%
  %
  \pgfextractx{\tikzuml@AC@xa}{\pgfpointanchor{\tikzumlAssemblyConnectorStart@nodeName}{center}}%
  \pgfextracty{\tikzuml@AC@ya}{\pgfpointanchor{\tikzumlAssemblyConnectorStart@nodeName}{center}}%
  \pgfextractx{\tikzuml@AC@xb}{\pgfpointanchor{\tikzumlAssemblyConnectorEnd@nodeName}{center}}%
  \pgfextracty{\tikzuml@AC@yb}{\pgfpointanchor{\tikzumlAssemblyConnectorEnd@nodeName}{center}}%
  %
  \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{--}}{%
    \ifthenelse{\tikzuml@AC@xb>\tikzuml@AC@xa}{%
      \def\tikzumlAssemblyConnectorStartAnchor{east}%
      \def\tikzumlAssemblyConnectorEndAnchor{west}%
    }{%
      \def\tikzumlAssemblyConnectorStartAnchor{west}%
      \def\tikzumlAssemblyConnectorEndAnchor{east}%
    }
  }{}%
  %
  \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|}}{%
    \ifthenelse{\tikzuml@AC@xb>\tikzuml@AC@xa}{%
      \def\tikzumlAssemblyConnectorStartAnchor{east}%
    }{%
      \def\tikzumlAssemblyConnectorStartAnchor{west}%
    }
    \ifthenelse{\tikzuml@AC@yb>\tikzuml@AC@ya}{%
      \def\tikzumlAssemblyConnectorEndAnchor{south}%
    }{%
      \def\tikzumlAssemblyConnectorEndAnchor{north}%
    }
  }{}%
  %
  \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-}}{%
    \ifthenelse{\tikzuml@AC@xb>\tikzuml@AC@xa}{%
      \def\tikzumlAssemblyConnectorEndAnchor{west}%
    }{%
      \def\tikzumlAssemblyConnectorEndAnchor{east}%
    }
    \ifthenelse{\tikzuml@AC@yb>\tikzuml@AC@ya}{%
      \def\tikzumlAssemblyConnectorStartAnchor{north}%
    }{%
      \def\tikzumlAssemblyConnectorStartAnchor{south}%
    }
  }{}%
  %
  \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|-}}{%
    \ifthenelse{\equal{\tikzumlAssemblyConnectorStartArm}{auto}}{%
      \ifthenelse{\equal{\tikzumlAssemblyConnectorEndArm}{auto}}{%
	\pgfmathsetlength{\tikzuml@AC@middleArm}{0.5 * \tikzuml@AC@xa + 0.5 * \tikzuml@AC@xb}%
      }{%
        \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@xb+\tikzumlAssemblyConnectorEndArm}%
      }%
    }{%
      \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@xa+\tikzumlAssemblyConnectorStartArm}%
    }%
    \pgfmathparse{\tikzuml@AC@middleArm>\tikzuml@AC@xa}
    \pgfmathparse{\tikzuml@AC@middleArm>\tikzuml@AC@xb}
    \ifthenelse{\lengthtest{\tikzuml@AC@middleArm>\tikzuml@AC@xa}}{%
      \def\tikzumlAssemblyConnectorStartAnchor{east}%
    }{%
      \def\tikzumlAssemblyConnectorStartAnchor{west}%
    }
    \ifthenelse{\lengthtest{\tikzuml@AC@middleArm>\tikzuml@AC@xb}}{%
      \def\tikzumlAssemblyConnectorEndAnchor{east}%
    }{%
      \def\tikzumlAssemblyConnectorEndAnchor{west}%
    }
  }{}%
  %
  \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-|}}{%
    \ifthenelse{\equal{\tikzumlAssemblyConnectorStartArm}{auto}}{%
      \ifthenelse{\equal{\tikzumlAssemblyConnectorEndArm}{auto}}{%
	\pgfmathsetlength{\tikzuml@AC@middleArm}{0.5 * \tikzuml@AC@ya + 0.5 * \tikzuml@AC@yb}%
      }{%
        \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@yb+\tikzumlAssemblyConnectorEndArm}%
      }%
    }{%
      \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@ya+\tikzumlAssemblyConnectorStartArm}%
    }%
    \ifthenelse{\tikzuml@AC@middleArm>\tikzuml@AC@ya}{%
      \def\tikzumlAssemblyConnectorStartAnchor{north}%
    }{%
      \def\tikzumlAssemblyConnectorStartAnchor{south}%
    }
    \ifthenelse{\tikzuml@AC@middleArm>\tikzuml@AC@yb}{%
      \def\tikzumlAssemblyConnectorEndAnchor{north}%
    }{%
      \def\tikzumlAssemblyConnectorEndAnchor{south}%
    }
  }{}%
  %
  \ifthenelse{\equal{\umlAssemblyConnectorStartAnchor}{}}{%
  }{%
    \def\tikzumlAssemblyConnectorStartAnchor{\umlAssemblyConnectorStartAnchor}%
  }%
  \ifthenelse{\equal{\umlAssemblyConnectorEndAnchor}{}}{%
  }{%
    \def\tikzumlAssemblyConnectorEndAnchor{\umlAssemblyConnectorEndAnchor}%
  }%
  %
  \node[inner sep=0] (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) at (\tikzumlAssemblyConnectorStart@nodeName.\tikzumlAssemblyConnectorStartAnchor) {};%
  \node[inner sep=0] (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) at (\tikzumlAssemblyConnectorEnd@nodeName.\tikzumlAssemblyConnectorEndAnchor) {};%
  %
  \umlrelation[style={tikzuml connector style}, #1]{\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp}{\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp}%
  %
  \ifthenelse{\equal{\tikzumlAssemblyConnectorWithPort}{tikzumlTrue}}{%
    \node[inner sep=0.5*\tikzumlAssemblyConnectorWidth, rectangle, draw=\tikzumlassemblyconnectordraw, fill=\tikzumlassemblyconnectorportfill] (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) {};%
    \node[inner sep=0.5*\tikzumlAssemblyConnectorWidth, rectangle, draw=\tikzumlassemblyconnectordraw, fill=\tikzumlassemblyconnectorportfill] (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) {};%
  }{%
    \node[inner sep=0] (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorStart@nodeName.\tikzumlAssemblyConnectorStartAnchor) {};%
    \node[inner sep=0] (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorEnd@nodeName.\tikzumlAssemblyConnectorEndAnchor) {};%
  }%
  %
  \addtocounter{tikzumlRelationNum}{-1}%
  \ifthenelse{\equal{\tikzumlAssemblyConnectorName}{connector-\thetikzumlConnectorNum}}{%
    \edef\tikzumlAssemblyConnectorName{relation-\thetikzumlRelationNum}%
    \edef\tikzumlAssemblyConnectorSymbolName{\tikzumlAssemblyConnectorLabel@nodeName}%
  }{%
    \edef\tikzumlAssemblyConnectorSymbolName{\tikzumlAssemblyConnectorName}%
  }%
  %
  \stepcounter{tikzumlRelationNum}%
  %
  \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{--}}{%
    \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorEnd@nodeName}%
  }{%
    \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|}}{%
      \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{%
        \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}%
      }{%
        \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorEnd@nodeName}%
      }%
    }{%
      \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-}}{%
        \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{%
          \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}%
        }{%
          \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorEnd@nodeName}%
        }%
      }{%
        \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|-}}{%
          \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{%
            \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}%
          }{%
            \ifthenelse{\equal{\tikzumlAssemblyConnectorLastArm}{tikzumlTrue}}{%
              \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-4}{\tikzumlAssemblyConnectorEnd@nodeName}%
            }{%
              \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorName-4}%
            }%
          }%
        }{%
          \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-|}}{%
            \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{%
              \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}%
            }{%
              \ifthenelse{\equal{\tikzumlAssemblyConnectorLastArm}{tikzumlTrue}}{%
                \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-4}{\tikzumlAssemblyConnectorEnd@nodeName}%
              }{%
                \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorName-4}%
              }%
            }%
          }{}%
        }%
      }%
    }%
  }%
  \stepcounter{tikzumlConnectorNum}%
}%

% shortcuts of \umlassemblyconnector
\newcommand{\umlHVassemblyconnector}[3][]{%
  \pgfkeys{/tikzuml/HVassemblyconnector/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
               \errmessage{TIKZUML ERROR : in umlHVassemblyconnector, forbidden option geometry}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/HVassemblyconnector/.cd, #1}%
  \umlassemblyconnector[geometry=-|, #1]{#2}{#3}%
}%

\newcommand{\umlVHassemblyconnector}[3][]{%
  \pgfkeys{/tikzuml/VHassemblyconnector/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
        \errmessage{TIKZUML ERROR : in umlVHassemblyconnector, forbidden option geometry}%
      }{}%
    }%
  }%
  \pgfkeys{/tikzuml/VHassemblyconnector/.cd, #1}%
  \umlassemblyconnector[geometry=|-, #1]{#2}{#3}%
}%

\newcommand{\umlHVHassemblyconnector}[3][]{%
  \pgfkeys{/tikzuml/HVHassemblyconnector/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
               \errmessage{TIKZUML ERROR : in umlHVHassemblyconnector, forbidden option geometry}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/HVHassemblyconnector/.cd, #1}%
  \umlassemblyconnector[geometry=-|-, #1]{#2}{#3}%
}%

\newcommand{\umlVHVassemblyconnector}[3][]{%
  \pgfkeys{/tikzuml/VHVassemblyconnector/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}}{%
               \errmessage{TIKZUML ERROR : in umlVHVassemblyconnector, forbidden option geometry}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/VHVassemblyconnector/.cd, #1}%
  \umlassemblyconnector[geometry=|-|, #1]{#2}{#3}%
}%

\newcommand{\umlport}[3][]{%
  \pgfkeys{/tikzuml/port/.cd,%
           draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillportcolor,%
           width/.initial=1em,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \errmessage{TIKZUML ERROR : in umlport forbidden option \keyname}%
           }}%
  \pgfkeys{/tikzuml/port/.cd, #1}%
  \pgfkeys{/tikzuml/port/.cd,%
           width/.get=\tikzumlPortWidth,%
           draw/.get=\tikzumlportdraw, fill/.get=\tikzumlportfill}%
  \edef\tikzumlPort@name{#2}%
  \edef\tikzumlPort@anchor{#3}%
  \begingroup%
    \def\_{_}\edef\x{\endgroup%
      \def\noexpand\tikzumlPort@nodeName{\tikzumlPort@name}}\x%
  %
  \node[inner sep=0.5*\tikzumlPortWidth, rectangle, draw=\tikzumlportdraw, fill=\tikzumlportfill] (\tikzumlPort@nodeName-\tikzumlPort@anchor-port) at (\tikzumlPort@nodeName.\tikzumlPort@anchor) {};
}

\newcommand{\umldelegateconnector}[3][]{%
  \def\tikzumlDelegateConnectorWithStartPort{tikzumlFalse}%
  \def\tikzumlDelegateConnectorWithEndPort{tikzumlFalse}%
  \pgfkeys{/tikzuml/delegateconnector/.cd,
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umldelegateconnector, forbidden option stereo}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/delegateconnector/.cd, #1}%
  \umlrelation[style={tikzuml connector style}, stereo=delegate, #1]{#2}{#3}%
}%


% shortcuts of \umldelegateconnector
\newcommand{\umlHVdelegateconnector}[3][]{%
  \pgfkeys{/tikzuml/HVdelegateconnector/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlHVdelegateconnector, forbidden option \keyname}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/HVdelegateconnector/.cd, #1}%
  \umldelegateconnector[geometry=-|, #1]{#2}{#3}%
}%

\newcommand{\umlVHdelegateconnector}[3][]{%
  \pgfkeys{/tikzuml/VHdelegateconnector/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlVHdelegateconnector, forbidden option \keyname}%
             }{}%
            }}%
  \pgfkeys{/tikzuml/VHdelegateconnector/.cd, #1}%
  \umldelegateconnector[geometry=|-, #1]{#2}{#3}%
}%

\newcommand{\umlHVHdelegateconnector}[3][]{%
  \pgfkeys{/tikzuml/HVHdelegateconnector/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlHVHdelegateconnector, forbidden option \keyname}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/HVHdelegateconnector/.cd, #1}%
  \umldelegateconnector[geometry=-|-, #1]{#2}{#3}%
}%

\newcommand{\umlVHVdelegateconnector}[3][]{%
  \pgfkeys{/tikzuml/VHVdelegateconnector/.cd,%
           .unknown/.code={%
             \let\keyname=\pgfkeyscurrentname%
             \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{%
               \errmessage{TIKZUML ERROR : in umlVHVdelegateconnector, forbidden option \keyname}%
             }{}%
           }}%
  \pgfkeys{/tikzuml/VHVdelegateconnector/.cd, #1}%
  \umldelegateconnector[geometry=|-|, #1]{#2}{#3}%
}%
%%% End of tikz-uml.sty
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%