%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Start of tikz-umld.sty
% Some macros for UML Diagrams.
% Repository: https://github.com/imol-ai/tikz-umld
% Maintainer: David Imolai
% Version: 1.0.0 (2026-10-07)
% Derived from TikZ-UML 1.0 by Nicolas Kielbasiewicz.
% This work may be distributed and/or modified under the terms of the
% GNU Affero General Public License, version 3 or (at your option) any later
% version. See LICENSE.md and NOTICE.md.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesPackage{tikz-umld}[2026/10/07 v1.0.0 TikZ UML diagrams]

\RequirePackage{ifthen,tikz,xstring,calc,pgfopts,etoolbox}
\usetikzlibrary{backgrounds,arrows,arrows.meta,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,
	x/.initial=0, y/.initial=0,
	package type/.initial=tikzumlEmpty, fill package/.initial=blue!15,
	class width/.initial=10ex, simple interface width/.initial=4ex, class type/.initial=class, fill class/.initial=cyan!30, fill template/.initial=yellow!2,
	narynode width/.initial=6ex,
	relation geometry/.initial=--, relation angle1/.initial=-30, relation angle2/.initial=30, relation loopsize/.initial=3em, relation weight/.initial=0.5, relation pos1/.initial=0.2, relation pos2/.initial=0.8, relation pos stereo/.initial=0.5,
	note width/.initial=3cm, fill note/.initial=yellow!30,
	fill system/.initial=white,
	fill usecase/.initial=orange!30,
	actor below/.initial=0.5cm,
	state join width/.initial=3ex,
	state decision width/.initial=3ex,
	state initial width/.initial=5ex,
	state final width/.initial=5.5ex,
	state enter width/.initial=5ex,
	state exit width/.initial=5ex,
	state end width/.initial=5ex,
	state history width/.initial=5ex,
	state deep history width/.initial=5ex,
	state width/.initial=8ex, fill state/.initial=orange!30,
	object stereo/.initial=object, fill object/.initial=orange!30,
	call dt/.initial=tikzumlEmpty, call padding/.initial=2, call type/.initial=synchron, fill call/.initial=yellow!30,
	fragment type/.initial=opt, fragment inner xsep/.initial=1, fragment inner ysep/.initial=1, fill fragment/.initial= none,
	create call dt/.initial=4,
	component width/.initial=8ex, fill component/.initial= yellow!30,
	required interface distance/.initial=2.5cm, required interface width/.initial=1em, required interface padding/.initial=1cm,
	provided interface distance/.initial=3cm, provided interface width/.initial=1em, provided interface padding/.initial=1cm,
	port width/.initial=1ex, fill port/.initial= yellow!30,
	fill assembly connector/.initial= white,
	.unknown/.code={
		\let\keyname=\pgfkeyscurrentname
		\let\keyvalue=\pgfkeyscurrentvalue
		\errmessage{TIKZUML ERROR : in tikzuml global, invalid option \keyname}
	}
}

% Label-only assembly-connector options are consumed by \umlassemblyconnector.
% Declare no-op TikZ counterparts because connector options are also forwarded
% to the underlying relation renderer.
\tikzset{
	labelpos/.code={}
}

\pgfkeys{/tikzuml/.cd, text/.get=\tikzumlDefaultTextColor, draw/.get=\tikzumlDefaultDrawColor, font/.get=\tikzumlDefaultFont,
	x/.get=\tikzumlDefaultX, y/.get=\tikzumlDefaultY,
	package type/.get=\tikzumlPackageDefaultType, fill package/.get=\tikzumlPackageDefaultFillColor,
	class width/.get=\tikzumlClassDefaultWidth, simple interface width/.get=\tikzumlSimpleInterfaceDefaultWidth, class type/.get=\tikzumlClassDefaultType, fill class/.get=\tikzumlClassDefaultFillColor, fill template/.get=\tikzumlClassTemplateFillColorDefaultFillColor,
	narynode width/.get=\tikzumlNaryNodeDefaultWidth,
	relation geometry/.get=\tikzumlRelationDefaultGeometry, relation angle1/.get=\tikzumlRelationDefaultAngleO, relation angle2/.get=\tikzumlRelationDefaultAngleT, relation loopsize/.get=\tikzumlRelationDefaultLoopSize, relation weight/.get=\tikzumlRelationDefaultWeight, relation pos1/.get=\tikzumlRelationDefaultPosO, relation pos2/.get=\tikzumlRelationDefaultPosT, relation pos stereo/.get=\tikzumlRelationDefaultPosStereo,
	note width/.get=\tikzumlNoteDefaultWidth, fill note/.get=\tikzumlNoteDefaultFillColor,
	fill system/.get=\tikzumlSystemDefaultFillColor,
	fill usecase/.get=\tikzumlUseCaseDefaultFillColor,
	actor below/.get=\tikzumlActorDefaultBelow,
	state join width/.get=\tikzumlStateJoinDefaultWidth,
	state decision width/.get=\tikzumlStateDecisionDefaultWidth,
	state initial width/.get=\tikzumlStateInitialDefaultWidth,
	state final width/.get=\tikzumlStateFinalDefaultWidth,
	state enter width/.get=\tikzumlStateEnterDefaultWidth,
	state exit width/.get=\tikzumlStateExitDefaultWidth,
	state end width/.get=\tikzumlStateEndDefaultWidth,
	state history width/.get=\tikzumlStateHistoryDefaultWidth,
	state deep history width/.get=\tikzumlStateDeepHistoryDefaultWidth,
	state width/.get=\tikzumlStateDefaultWidth, fill state/.get=\tikzumlStateDefaultFillColor,
	object stereo/.get=\tikzumlObjectDefaultStereo, fill object/.get=\tikzumlObjectDefaultFillColor,
	call dt/.get=\tikzumlCallDefaultDT, call padding/.get=\tikzumlCallDefaultPadding, call type/.get=\tikzumlCallDefaultType, fill call/.get=\tikzumlCallDefaultFillColor,
	fragment type/.get=\tikzumlFragmentDefaultType, fragment inner xsep/.get=\tikzumlFragmentDefaultXSep, fragment inner ysep/.get=\tikzumlFragmentDefaultYSep, fill fragment/.get=\tikzumlFragmentDefaultFillColor,
	create call dt/.get=\tikzumlCreateCallDefaultDT,
	component width/.get=\tikzumlComponentDefaultWidth, fill component/.get=\tikzumlComponentDefaultFillColor,
	required interface distance/.get=\tikzumlRequiredInterfaceDefaultDistance, required interface width/.get=\tikzumlRequiredInterfaceDefaultWidth, required interface padding/.get=\tikzumlRequiredInterfaceDefaultPadding,
	provided interface distance/.get=\tikzumlProvidedInterfaceDefaultDistance, provided interface width/.get=\tikzumlProvidedInterfaceDefaultWidth, provided interface padding/.get=\tikzumlProvidedInterfaceDefaultPadding,
	port width/.get=\tikzumlPortDefaultWidth, fill port/.get=\tikzumlPortDefaultFillColor,
	fill assembly connector/.get=\tikzumlAssemblyConnectorDefaultFillColor
}

% utility : change default colors
\newcommand{\tikzumlset}[1]{
	\pgfkeys{/tikzuml/.cd,#1}
	\pgfkeys{/tikzuml/.cd, text/.get=\tikzumlDefaultTextColor, draw/.get=\tikzumlDefaultDrawColor, font/.get=\tikzumlDefaultFont,
		x/.get=\tikzumlDefaultX, y/.get=\tikzumlDefaultY,
		package type/.get=\tikzumlPackageDefaultType, fill package/.get=\tikzumlPackageDefaultFillColor,
		class width/.get=\tikzumlClassDefaultWidth, simple interface width/.get=\tikzumlSimpleInterfaceDefaultWidth, class type/.get=\tikzumlClassDefaultType, fill class/.get=\tikzumlClassDefaultFillColor, fill template/.get=\tikzumlClassTemplateFillColorDefaultFillColor,
		narynode width/.get=\tikzumlNaryNodeWidth,
		relation geometry/.get=\tikzumlRelationDefaultGeometry, relation angle1/.get=\tikzumlRelationDefaultAngleO, relation angle2/.get=\tikzumlRelationDefaultAngleT, relation loopsize/.get=\tikzumlRelationDefaultLoopSize, relation weight/.get=\tikzumlRelationDefaultWeight, relation pos1/.get=\tikzumlRelationDefaultPosO, relation pos2/.get=\tikzumlRelationDefaultPosT, relation pos stereo/.get=\tikzumlRelationDefaultPosStereo,
		note width/.get=\tikzumlNoteDefaultWidth, fill note/.get=\tikzumlNoteDefaultFillColor,
		fill system/.get=\tikzumlSystemDefaultFillColor,
		fill usecase/.get=\tikzumlUseCaseDefaultFillColor,
		actor below/.get=\tikzumlActorDefaultBelow,
		state join width/.get=\tikzumlStateJoinDefaultWidth,
		state decision width/.get=\tikzumlStateDecisionDefaultWidth,
		state initial width/.get=\tikzumlStateInitialDefaultWidth,
		state final width/.get=\tikzumlStateFinalDefaultWidth,
		state enter width/.get=\tikzumlStateEnterDefaultWidth,
		state exit width/.get=\tikzumlStateExitDefaultWidth,
		state end width/.get=\tikzumlStateEndDefaultWidth,
		state history width/.get=\tikzumlStateHistoryDefaultWidth,
		state deep history width/.get=\tikzumlStateDeepHistoryDefaultWidth,
		state width/.get=\tikzumlStateDefaultWidth, fill state/.get=\tikzumlStateDefaultFillColor,
		object stereo/.get=\tikzumlObjectDefaultStereo, fill object/.get=\tikzumlObjectDefaultFillColor,
		call dt/.get=\tikzumlCallDefaultDT, call padding/.get=\tikzumlCallDefaultPadding, call type/.get=\tikzumlCallDefaultType, fill call/.get=\tikzumlCallDefaultFillColor,
		fragment type/.get=\tikzumlFragmentDefaultType, fragment inner xsep/.get=\tikzumlFragmentDefaultXSep, fragment inner ysep/.get=\tikzumlFragmentDefaultYSep, fill fragment/.get=\tikzumlFragmentDefaultFillColor,
		create call dt/.get=\tikzumlCreateCallDT,
		component width/.get=\tikzumlComponentDefaultWidth, fill component/.get=\tikzumlComponentDefaultFillColor,
		required interface distance/.get=\tikzumlRequiredInterfaceDefaultDistance, required interface width/.get=\tikzumlRequiredInterfaceDefaultWidth, required interface padding/.get=\tikzumlRequiredInterfaceDefaultPadding,
		provided interface distance/.get=\tikzumlProvidedInterfaceDefaultDistance, provided interface width/.get=\tikzumlProvidedInterfaceDefaultWidth, provided interface padding/.get=\tikzumlProvidedInterfaceDefaultPadding,
		port width/.get=\tikzumlPortDefaultWidth, fill port/.get=\tikzumlPortDefaultFillColor,
		fill assembly connector/.get=\tikzumlAssemblyConnectorDefaultFillColor
	}
}

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

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                       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 simpleinterface style}=[circle, minimum height=1em, node distance=1em]
\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 enumeration style}=[rectangle split, rectangle split parts=2, rectangle split part align={center, 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=\tikzumlDefaultDrawColor, -]
\tikzstyle{tikzuml bidirectional association style}=[color=\tikzumlDefaultDrawColor, {Straight Barb[scale=3.5,angle'=55]}-{Straight Barb[scale=3.5,angle'=55]}]
\tikzstyle{tikzuml unidirectional association style}=[color=\tikzumlDefaultDrawColor, -{Straight Barb[scale=3.5,angle'=55]}]
\tikzstyle{tikzuml aggregation style}=[color=\tikzumlDefaultDrawColor, {Diamond[scale=3, open]}-]
\tikzstyle{tikzuml unidirectional aggregation style}=[color=\tikzumlDefaultDrawColor, {Diamond[scale=3, open]}-{Straight Barb[scale=3.5,angle'=55]}]
\tikzstyle{tikzuml composition style}=[color=\tikzumlDefaultDrawColor, {Diamond[scale=3]}-]
\tikzstyle{tikzuml unidirectional composition style}=[color=\tikzumlDefaultDrawColor, {Diamond[scale=3]}-{Straight Barb[scale=3.5,angle'=55]}]
\tikzstyle{tikzuml nesting style}=[color=\tikzumlDefaultDrawColor]
\tikzstyle{tikzuml dependency style}=[color=\tikzumlDefaultDrawColor, -{Straight Barb[scale=3.5,angle'=55]}, dashed]
\tikzstyle{tikzuml import style}=[color=\tikzumlDefaultDrawColor, -{Straight Barb[scale=3.5,angle'=55]}, dashed]
\tikzstyle{tikzuml inherit style}=[color=\tikzumlDefaultDrawColor, -{Triangle[scale=2.5,open,angle'=50]}]
\tikzstyle{tikzuml implements style}=[color=\tikzumlDefaultDrawColor, -{Triangle[scale=2.5,open,angle'=50]}, 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\iftikzumlpackageSimpleStyle
\newif\iftikzumlclassSimpleStyle
\newif\iftikzumlclassCircleShape
\newif\iftikzumlpackageWithoutCoords
\newif\iftikzumlclassWithoutCoords
\newif\iftikzumlassocclassWithoutCoords
\newif\iftikzumlnoteWithoutCoords

% define a uml package
% arg : package name
% optional : x, y: coordinates of the package
%            type: stereotype of the package
%            name: name of the package node
%            draw, fill, text: colors
%            style: to manage every default TikZ option
%            no coords: to tell that the package position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newenvironment{umlpackage}[2][]{
	\pgfkeys{/tikzuml/package/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, style/.style={},
		name/.initial=tikzumlEmpty, type/.initial=\tikzumlPackageDefaultType, draw/.initial=\tikzumlDefaultDrawColor,
		fill/.initial=\tikzumlPackageDefaultFillColor, text/.initial=\tikzumlDefaultTextColor,
		no coords/.is if=tikzumlpackageWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/package/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/package/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/package/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlpackage, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/package/.cd, #1}
	\pgfkeys{/tikzuml/package/.cd, x/.get=\tikzumlPackageXShift, y/.get=\tikzumlPackageYShift, name/.get=\tikzumlPackageName, type/.get=\tikzumlPackageTypeTmp,
		draw/.get=\tikzumlPackageDrawColor, fill/.get=\tikzumlPackageFillColor,
		text/.get=\tikzumlPackageTextColor
	}



	\ifthenelse{\equal{\tikzumlPackageTypeTmp}{tikzumlEmpty}}{
		\def\tikzumlPackageType{}
	}{
		\expandafter\def\expandafter\tikzumlPackageType\expandafter{$\ll$\tikzumlPackageTypeTmp$\gg$ \\}
	}

	\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=\tikzumlPackageXShift cm, yshift=\tikzumlPackageYShift cm]
}{
	\addtocounter{tikzumlPackageLevel}{-1}
	\begin{pgfonlayer}{package\thetikzumlPackageLevel}

	% if contains no class, and not simple, one define a fictive node to enable the fit option
	\ifnum\c@tikzumlPackageClassNum=0
		\ifnum\c@tikzumlPackageSubPackageNum=0
			\iftikzumlpackageWithoutCoords
				\node[inner sep=1.5ex, /tikzuml/package/style] (\tikzumlPackage@nodeName-root) {\phantom{\tikzumlPackage@nodeName}};
			\else
				\node[inner sep=1.5ex, /tikzuml/package/style] (\tikzumlPackage@nodeName-root) at (0,0) {\phantom{\tikzumlPackage@nodeName}};
			\fi
			\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=\tikzumlPackageDrawColor, fill=\tikzumlPackageFillColor, text=\tikzumlPackageTextColor, font=\tikzumlDefaultFont, inner sep=1.5ex, /tikzuml/package/style, fit = \csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname] (\tikzumlPackage@nodeName) {};
	\node[draw=\tikzumlPackageDrawColor, fill=\tikzumlPackageFillColor, text=\tikzumlPackageTextColor, font=\tikzumlDefaultFont, minimum height=1.5em, outer ysep=-0.3, anchor=south west] (\tikzumlPackage@nodeName-caption) at (\tikzumlPackage@nodeName.north west) {\begin{tabular}{c} \tikzumlPackageType \textbf{\tikzumlPackage@name}\end{tabular}};
	\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: type of class (class, interface, typedef, enum)
%            tags: tagged values of class
%            template: template parameters
%            simple: if used, class is empty and drawn with a rectangle
%            circle: if used with simple, class is empty and drawn with a circle
%            draw, fill, fill template, and text: colors
%            style: to manage every default TikZ option
%            no coords: to tell that the class position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlclass}[4][]{
	\pgfkeys{/tikzuml/class/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlClassDefaultWidth, type/.initial=\tikzumlClassDefaultType,
		tags/.initial={}, style/.style={},
		template/.initial={}, name/.initial=tikzumlEmpty,
		draw/.initial=\tikzumlDefaultDrawColor,
		fill template/.initial=\tikzumlClassTemplateFillColorDefaultFillColor,
		fill/.initial=\tikzumlClassDefaultFillColor,
		text/.initial=\tikzumlDefaultTextColor,
		simple/.is if=tikzumlclassSimpleStyle, circle/.is if=tikzumlclassCircleShape, no coords/.is if=tikzumlclassWithoutCoords,
		simple=false, circle=false, no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/class/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/class/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/class/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlclass, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/class/.cd,#1}

	\iftikzumlclassSimpleStyle
		\iftikzumlclassCircleShape
			\pgfkeys{/tikzuml/class/.cd, width/.initial=\tikzumlSimpleInterfaceDefaultWidth}
		\fi
	\fi

	\pgfkeys{/tikzuml/class/.cd, x/.get=\tikzumlClassX, y/.get=\tikzumlClassY, width/.get=\tikzumlClassMinimumWidth,
		type/.get=\tikzumlClassTypeTmp, tags/.get=\tikzumlClassTagsTmp, template/.get=\tikzumlClassTemplateFillColorParam,
		name/.get=\tikzumlClassName,
		draw/.get=\tikzumlClassDrawColor, fill/.get=\tikzumlClassFillColor,
		text/.get=\tikzumlClassTextColor, fill template/.get=\tikzumlClassTemplateFillColor
	}

	\ifthenelse{\equal{\tikzumlClassTypeTmp}{class}\OR\equal{\tikzumlClassTypeTmp}{object}}{
		\def\tikzumlClassType{}
	}{
		\expandafter\def\expandafter\tikzumlClassType\expandafter{$\ll$\tikzumlClassTypeTmp$\gg$ \\}
	}

	\ifthenelse{\equal{\tikzumlClassTagsTmp}{}}{
		\def\tikzumlClassTags{}
	}{
		\def\tikzumlClassTags{\\ \{\tikzumlClassTagsTmp\}}
	}

	\ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{
		\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{\tikzumlClassName}{tikzumlEmpty}}{}{
		\def\tikzumlClassNodeName{\tikzumlClassName}
	}

	\StrSubstitute{\tikzumlClassNodeName}{:}{@COLON@}[\tikzumlClassNodeName]
	\StrSubstitute{\tikzumlClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlClassNodeName]

	\ifthenelse{\equal{\tikzumlClassTypeTmp}{abstract}}{
		\let\tikzumlClassNameOld\tikzumlClassName
		\def\tikzumlClassName{{\emph \tikzumlClassNameOld}}
	}{}
	\ifthenelse{\equal{\tikzumlClassTypeTmp}{object}}{
		\let\tikzumlClassNameOld\tikzumlClassName
		\def\tikzumlClassName{{\underline \tikzumlClassNameOld}}
	}{}
	\ifthenelse{\equal{\tikzumlClassTypeTmp}{interface}}{
		\let\tikzumlClassNameOld\tikzumlClassName
		\def\tikzumlClassName{{\emph \tikzumlClassNameOld}}
	}{}

	\def\tikzumlClassPos{\tikzumlClassX,\tikzumlClassY}
	\def\tikzumlClassAttributes{#3}
	\def\tikzumlClassOperations{#4}

	\iftikzumlclassSimpleStyle
		\iftikzumlclassWithoutCoords
			\iftikzumlclassCircleShape
				\node[tikzuml simpleinterface style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) {};
				\node[anchor=south] (\tikzumlClassNodeName-label) at (\tikzumlClassNodeName.north) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}
				};
			\else
				\node[tikzuml simpleclass style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}
				};
			\fi
		\else
			\iftikzumlclassCircleShape
				\node[tikzuml simpleinterface style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) at (\tikzumlClassPos) {};
				\node[anchor=south] (\tikzumlClassNodeName-label) at (\tikzumlClassNodeName.north){\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}
				};
			\else
				\node[tikzuml simpleclass style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) at (\tikzumlClassPos) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}
				};
			\fi
		\fi
	\else
		\ifthenelse{\equal{\tikzumlClassTypeTmp}{enumeration}}{
			\def\tikzumlClassStyleTmp{tikzuml enumeration style}
		}{
			\def\tikzumlClassStyleTmp{tikzuml class style}
		}
		\iftikzumlclassWithoutCoords
			\node[\tikzumlClassStyleTmp, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}
				\nodepart{second}
				\begin{tabular}{l}
				\tikzumlClassAttributes
				\end{tabular}
				\ifthenelse{\equal{\tikzumlClassTypeTmp}{enumeration}}{}{
					\nodepart{third}
					\begin{tabular}{l}
					\tikzumlClassOperations
					\end{tabular}
				}
			};
		\else
			\node[\tikzumlClassStyleTmp, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) at (\tikzumlClassPos) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}
				\nodepart{second}
				\begin{tabular}{l}
				\tikzumlClassAttributes
				\end{tabular}
				\ifthenelse{\equal{\tikzumlClassTypeTmp}{enumeration}}{}{
					\nodepart{third}
					\begin{tabular}{l}
					\tikzumlClassOperations
					\end{tabular}
				}
			};
		\fi
	\fi


	\ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{}{
		\draw (\tikzumlClassNodeName.north east) node[tikzuml template style, name=\tikzumlClassNodeName-template, draw=\tikzumlClassDrawColor, fill=\tikzumlClassTemplateFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont] {\tikzumlClassTemplateFillColorParam};
	}

	% add to fit
	\ifnum\c@tikzumlPackageLevel>0
		\edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}
		\ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{
			\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
		\def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname}
		\ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{
			\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][]{
	\pgfkeys{/tikzuml/class/.cd, .unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{type}}{
				\errmessage{TIKZUML ERROR : in umlabstract, forbidden option type}
			}{}
		}
	}
	\pgfkeys{/tikzuml/class/.cd, #1}
	\umlclass[type=abstract,#1]{#2}{#3}{#4}
}
\newcommand{\umlobj}[4][]{
	\pgfkeys{/tikzuml/class/.cd, .unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{type}}{
				\errmessage{TIKZUML ERROR : in umlobj, forbidden option type}
			}{}
		}
	}
	\pgfkeys{/tikzuml/class/.cd, #1}
	\umlclass[type=object,#1]{#2}{#3}{#4}
}
\newcommand{\umlinterface}[4][]{
	\pgfkeys{/tikzuml/class/.cd, .unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{type}}{
				\errmessage{TIKZUML ERROR : in umlinterface, forbidden option type}
			}{}
		}
	}
	\pgfkeys{/tikzuml/class/.cd, #1}
	\umlclass[type=interface,#1]{#2}{#3}{#4}
}
\newcommand{\umltypedef}[4][]{
	\pgfkeys{/tikzuml/class/.cd, .unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{type}}{
				\errmessage{TIKZUML ERROR : in umltypedef, forbidden option type}
			}{}
		}
	}
	\pgfkeys{/tikzuml/class/.cd, #1}
	\umlclass[type=typedef,#1]{#2}{#3}{#4}
}
\newcommand{\umlenum}[3][]{
	\pgfkeys{/tikzuml/class/.cd, .unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{type}}{
				\errmessage{TIKZUML ERROR : in umlenum, forbidden option type}
			}{}
		}
	}
	\pgfkeys{/tikzuml/class/.cd, #1}
	\umlclass[type=enumeration,#1]{#2}{#3}{}
}

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

\newcommand{\umlsimpleinterface}[2][]{
	\pgfkeys{/tikzuml/class/.cd, .unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{simple}}{
				\errmessage{TIKZUML ERROR : in umlsimpleinterface, forbidden option simple}
			}{
				\ifthenelse{\equal{\keyname}{circle}}{
					\errmessage{TIKZUML ERROR : in umlsimpleinterface, forbidden option circle}
				}{}
			}
		}
	}
	\pgfkeys{/tikzuml/class/.cd, #1}
	\umlsimpleclass[circle, #1]{#2}
}

\newcommand{\umlsimpleobj}[2][]{
	\pgfkeys{/tikzuml/class/.cd, .unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{simple}}{
				\errmessage{TIKZUML ERROR : in umlsimpleobj, forbidden option simple}
			}{
				\ifthenelse{\equal{\keyname}{object}}{
					\errmessage{TIKZUML ERROR : in umlsimpleobj, forbidden option object}
				}{}
			}
		}
	}
	\pgfkeys{/tikzuml/class/.cd, #1}
	\umlsimpleclass[type=object, #1]{#2}
}

\newcommand\hunderfill{\leavevmode\leaders\vtop{\vskip1.175mm\hrule width .05pt}\hfill\kern0pt }

% define commands for uml constraints
\newcommand{\umlcon}[2]{#1 \hfill \{#2\}}
\newcommand{\umlstatic}[1]{\underline{#1}\hunderfill\underline{\{static\}}}
\newcommand{\umlpvirt}[1]{\textit{\umlcon{#1}{pure virtual}}}
\newcommand{\umlvirt}[1]{\umlcon{#1}{virtual}}
\newcommand{\umloverrd}[1]{\umlcon{#1}{override}}
\newcommand{\umlquery}[1]{\umlcon{#1}{query}}

% define node for n-ary association
\newcommand{\umlNarynode}[2][]{
	\def\tikzumlNaryNodeAnchor{.north}
	\def\tikzumlNaryNodeLabelPos{above}
	\pgfkeys{/tikzuml/narynode/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlNaryNodeDefaultWidth, name/.initial=tikzumlEmpty, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlClassDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, style/.style={}, .unknown/.code={
	\let\keyname=\pgfkeyscurrentname
	\let\keyvalue=\pgfkeyscurrentvalue
	\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}
								}{
									\ifx\keyvalue\pgfkeysnovalue
										\pgfkeys{/tikzuml/narynode/.cd, style/.append style/.expand once={\keyname}}
									\else
										\pgfkeys{/tikzuml/narynode/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
									\fi
									%\errmessage{TIKZUML ERROR : in umlNarynode, invalid option \keyname}
								}
							}
						}
					}
				}
			}
		}
	}}}
	\pgfkeys{/tikzuml/narynode/.cd,#1}
	\pgfkeys{/tikzuml/narynode/.cd, x/.get=\tikzumlNaryNodeX, y/.get=\tikzumlNaryNodeY, width/.get=\tikzumlNaryNodeMinimumWidth,
		name/.get=\tikzumlNaryNodeName,
		draw/.get=\tikzumlNaryNodeDrawColor, fill/.get=\tikzumlNaryNodeFillColor,
		text/.get=\tikzumlNaryNodeTextColor
	}

	\def\tikzumlNaryName{#2}

	\ifthenelse{\equal{\tikzumlNaryNodeName}{tikzumlEmpty}}{
		\edef\tikzumlNaryNodeName{\tikzumlNaryName}
	}{
		\edef\tikzumlNaryNodeName{\tikzumlNaryNodeName}
	}

	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlNaryNode@nodeName{\tikzumlNaryNodeName}}\x

	\StrSubstitute{\tikzumlNaryNode@nodeName}{:}{@COLON@}[\tikzumlNaryNode@nodeName]
	\StrSubstitute{\tikzumlNaryNode@nodeName}{\_}{@UNDERSCORE@}[\tikzumlNaryNode@nodeName]

	\def\tikzumlNarynodePos{\tikzumlNaryNodeX,\tikzumlNaryNodeY}

	\node[tikzuml narynode style, draw=\tikzumlNaryNodeDrawColor, fill=\tikzumlNaryNodeFillColor, text=\tikzumlNaryNodeTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlNaryNodeMinimumWidth, minimum height=\tikzumlNaryNodeMinimumWidth, /tikzuml/narynode/style] (\tikzumlNaryNode@nodeName) at (\tikzumlNarynodePos) {};
	\draw (\tikzumlNaryNode@nodeName\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 (\tikzumlNaryNode@nodeName)}
		\stepcounter{tikzumlPackageClassNum}
	\fi
}

\newdimen\tikzumlNestingSymbolSize

% main command to define a relation between two classes
% args : src class
%        dest class
% optional : geometry: geometry of the line
%            weight: barycentric weight of the middle part when geometry is a 3-line
%            arm1, arm2: lengths of first or last part when geometry id a 3-line
%            arg1, arg2, arg: name of the src/dest/dest side class type attribute defined by the relation
%            mult1, mult2, mult: multiplicity of the src/dest/dest side class type attribute defined by the relation
%            pos1, pos2, pos: position of the src/dest/dest side class type attribute defined by the relation
%            align1, align2, align: text justification of the src/dest/dest side class type attribute defined by the relation
%            anchor1, anchor2: src/dest anchors on linked classes
%            angle1, angle2, loopsize: start angle, end angle and size of the relation (only if recursive)
%            stereo: stereotype of the relation
%            st:pos, st:anchor, st:fill: stereotype position, anchor, and background
%            style: style of the relation (association, aggregation, composition, inherit, ...)
%            name: rootname used for naming nodes of the relation
%            recursive mode: type of recursive arrow (transition for state diagrams, or default)
%            recursive direction start/end: when transition relation, start/end directions of the relation arrow
\newcommand{\umlrelation}[3][]{
	\pgfkeys{/tikzuml/relation/.cd, geometry/.initial=\tikzumlRelationDefaultGeometry, weight/.initial=\tikzumlRelationDefaultWeight,
		arm1/.initial=auto, arm2/.initial=auto,
		arg1/.initial={}, arg2/.initial={}, arg/.initial={},
		mult1/.initial={}, mult2/.initial={}, mult/.initial={},
		pos1/.initial=\tikzumlRelationDefaultPosO, pos2/.initial=\tikzumlRelationDefaultPosT, pos/.initial=tikzumlEmpty,
		align1/.initial={}, align2/.initial={}, align/.initial={},
		anchor1/.initial=tikzumlEmpty, anchor2/.initial=tikzumlEmpty,
		angle1/.initial=\tikzumlRelationDefaultAngleO, angle2/.initial=\tikzumlRelationDefaultAngleT, loopsize/.initial=\tikzumlRelationDefaultLoopSize,
		stereo/.initial={}, st:pos/.initial=\tikzumlRelationDefaultPosStereo,
		st:anchor/.initial=center, st:fill/.initial=none,
		style/.initial=->, style2/.style={}, name/.initial=relation-\thetikzumlRelationNum,
		recursive mode/.initial=default, recursive direction start/.initial=right,
		recursive direction end/.initial=bottom,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\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}}{}{
					\ifx\keyvalue\pgfkeysnovalue
						\pgfkeys{/tikzuml/relation/.cd, style2/.append style/.expand once={\keyname}}
					\else
						\pgfkeys{/tikzuml/relation/.cd, style2/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
					\fi
					%\errmessage{TIKZUML ERROR : in umlrelation, invalid option \keyname}
			}
		}
	}
	\pgfkeys{/tikzuml/relation/.cd,#1}
	\pgfkeys{/tikzuml/relation/.cd, geometry/.get=\tikzumlRelationGeometry, weight/.get=\tikzumlRelationWeight,
		arm1/.get=\tikzumlRelationArmO, arm2/.get=\tikzumlRelationArmT,
		arg1/.get=\tikzumlRelationAttrName, arg2/.get=\tikzumlRelationAttrNameTO, arg/.get=\tikzumlRelationAttrNameTT,
		mult1/.get=\tikzumlRelationMultiplicity, mult2/.get=\tikzumlRelationMultiplicityTO, mult/.get=\tikzumlRelationMultiplicityTT,
		pos1/.get=\tikzumlRelationPosition, pos2/.get=\tikzumlRelationPositionTO, pos/.get=\tikzumlRelationPositionTT,
		align1/.get=\tikzumlRelationAlign, align2/.get=\tikzumlRelationAlignTO, align/.get=\tikzumlRelationAlignTT,
		anchor1/.get=\tikzumlRelationSrcAnchor, anchor2/.get=\tikzumlRelationDestAnchor,
		angle1/.get=\tikzumlRelationStartAngle, angle2/.get=\tikzumlRelationEndAngle, loopsize/.get=\tikzumlRelationLoopSize,
		stereo/.get=\tikzumlRelationStereoType, st:pos/.get=\tikzumlRelationPositionStereotype,
		st:anchor/.get=\tikzumlRelationStereotypeAnchor,
		st:fill/.get=\tikzumlRelationStereotypeFill,
		style/.get=\tikzumlRelationStyle, name/.get=\tikzumlRelationName,
		recursive mode/.get=\tikzumlRelationRecursiveMode,
		recursive direction start/.get=\tikzumlRelationRecursiveDirectionStart,
		recursive direction end/.get=\tikzumlRelationRecursiveDirectionEnd
	}

	\def\tikzumlSrcClassName{#2}

	% managing \_ in class names for node names
	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlSrcClassNodeName{\tikzumlSrcClassName}}\x

	\StrSubstitute{\tikzumlSrcClassNodeName}{:}{@COLON@}[\tikzumlSrcClassNodeName]
	\StrSubstitute{\tikzumlSrcClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlSrcClassNodeName]

	\def\tikzumlDestClassName{#3}
	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlDestClassNodeName{\tikzumlDestClassName}}\x

	\StrSubstitute{\tikzumlDestClassNodeName}{:}{@COLON@}[\tikzumlDestClassNodeName]
	\StrSubstitute{\tikzumlDestClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlDestClassNodeName]

	% managing alias keys
	\def\tikzumlRelationAttrNameT{\tikzumlRelationAttrNameTO\tikzumlRelationAttrNameTT}
	\def\tikzumlRelationMultiplicityT{\tikzumlRelationMultiplicityTO\tikzumlRelationMultiplicityTT}
	\def\tikzumlRelationAlignT{\tikzumlRelationAlignTO\tikzumlRelationAlignTT}
	\def\posAttrName{}
	\def\posMultiplicity{}
	\def\posAttrNameT{}
	\def\posMultiplicityT{}

	\ifthenelse{\equal{\tikzumlRelationPositionTT}{tikzumlEmpty}}{
		\def\tikzumlRelationPositionT{\tikzumlRelationPositionTO}
	}{
		\def\tikzumlRelationPositionT{\tikzumlRelationPositionTT}
	}

	\def\attrAlign{}
	\def\multAlign{}
	\def\attrAlignT{}
	\def\multAlignT{}

	\ifthenelse{\equal{\tikzumlRelationAlign}{left}}{
		\def\attrAlign{above right}
		\def\multAlign{below right}
	}{
		\ifthenelse{\equal{\tikzumlRelationAlign}{right}}{
			\def\attrAlign{above left}
			\def\multAlign{below left}
		}{}
	}

	\ifthenelse{\equal{\tikzumlRelationAlignT}{left}}{
		\def\attrAlignT{above right}
		\def\multAlignT{below right}
	}{
		\ifthenelse{\equal{\tikzumlRelationAlignT}{right}}{
			\def\attrAlignT{above left}
			\def\multAlignT{below left}
		}{}
	}

	% def stereotype
	\ifthenelse{\equal{\tikzumlRelationStereoType}{}}{
		\def\stereotype{}
	}{
		\def\stereotype{$\ll$\tikzumlRelationStereoType$\gg$}
	}

	% def anchors macros
	\ifthenelse{\equal{\tikzumlRelationSrcAnchor}{tikzumlEmpty}}{
		\def\tikzumlRelationSrcAnchor{}
	}{
		\let\tikzumlRelationSrcAnchorold\tikzumlRelationSrcAnchor
		\def\tikzumlRelationSrcAnchor{.\tikzumlRelationSrcAnchorold}
	}

	\ifthenelse{\equal{\tikzumlRelationDestAnchor}{tikzumlEmpty}}{
		\def\tikzumlRelationDestAnchor{}
	}{
		\let\tikzumlRelationDestAnchorold\tikzumlRelationDestAnchor
		\def\tikzumlRelationDestAnchor{.\tikzumlRelationDestAnchorold}
	}

	\setcounter{pos}{100*\real{\tikzumlRelationPosition}}
	\setcounter{posT}{100*\real{\tikzumlRelationPositionT}}
	\setcounter{posStereo}{100*\real{\tikzumlRelationPositionStereotype}}

	\pgfmathsetmacro{\tikzumlRelationWeightT}{1.0-\tikzumlRelationWeight}

	%\newcounter{tikzumlControlNodesNum}
	%\setcounter{tikzumlControlNodesNum}{0}

	\node[inner sep=0] (\tikzumlRelationName-middle) at (barycentric cs:\tikzumlSrcClassNodeName=\tikzumlRelationWeightT,\tikzumlDestClassNodeName=\tikzumlRelationWeight) {};

	% straight line
	\ifthenelse{\equal{\tikzumlRelationGeometry}{--}}
	{
		\ifthenelse{\equal{\tikzumlSrcClassNodeName}{\tikzumlDestClassNodeName}}{
			\def\arcNum{1}
			\def\arcNumT{1}

			\ifthenelse{\equal{\tikzumlRelationRecursiveMode}{default}}{
				\xdef\tikzumlLastArc{node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
					node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
					node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
					node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
					node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
				\xdef\tikzumlPath{(\tikzumlSrcClassNodeName)
					edge[in=\tikzumlRelationEndAngle, out=\tikzumlRelationStartAngle, distance=\tikzumlRelationLoopSize] \tikzumlLastArc
					node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} (\tikzumlDestClassNodeName)
				}
			}{
				\ifthenelse{\equal{\tikzumlRelationRecursiveMode}{transition}}{
					\xdef\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {}}
					\xdef\tikzumlMidOneArc{node[midway, inner sep=0, name=\tikzumlRelationName-3, anchor=center] {}}

					\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{\tikzumlRelationRecursiveDirectionEnd}}{
						\def\numArcs{3}
						\xdef\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {}}

						\begin{pgfonlayer}{connections}
						\draw (\tikzumlSrcClassNodeName) edge[in=\tikzumlRelationEndAngle, out=\tikzumlRelationStartAngle, distance=\tikzumlRelationLoopSize, draw=none]
						node[midway, inner sep=0, name=\tikzumlRelationName-tmp, anchor=center] {} (\tikzumlDestClassNodeName);
						\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}\OR\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{
							\node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle -| \tikzumlRelationName-tmp) {};
							\node[inner sep=0, name=\tikzumlRelationName-4] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle -| \tikzumlRelationName-tmp) {};
						}{
							\node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle |- \tikzumlRelationName-tmp) {};
							\node[inner sep=0, name=\tikzumlRelationName-4] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle |- \tikzumlRelationName-tmp) {};
						}
						\end{pgfonlayer}
					}{
						\def\numArcs{4}
						\xdef\tikzumlMidTwoArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {}}
						\xdef\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-7, anchor=center] {}}

						\begin{pgfonlayer}{connections}
						\draw (\tikzumlSrcClassNodeName) edge[in=\tikzumlRelationEndAngle, out=\tikzumlRelationStartAngle, distance=\tikzumlRelationLoopSize, draw=none]
						node[midway, name=\tikzumlRelationName-4, anchor=center] {} (\tikzumlDestClassNodeName);
						\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}\OR\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{
							\node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle -| \tikzumlRelationName-4) {};
							\node[inner sep=0, name=\tikzumlRelationName-6] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle |- \tikzumlRelationName-4) {};
						}{
							\node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle |- \tikzumlRelationName-4) {};
							\node[inner sep=0, name=\tikzumlRelationName-6] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle -| \tikzumlRelationName-4) {};
						}
						\end{pgfonlayer}
					}

					\ifnum\numArcs=4
						\ifnum\theposStereo>300
							\pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-300)/100}
							\xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype}}
						\else
							\ifnum\theposStereo<100
								\xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype}}
							\else
								\ifnum\theposStereo>200
									\pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100}
									\xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype}}
								\else
									\pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}
									\xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype}}
								\fi
							\fi
						\fi

						\ifthenelse{\thepos=300\OR\thepos=100}{
							\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{
									\def\posAttrName{above right}
									\def\posMultiplicity{below left}
								}{
									\def\posAttrName{above left}
									\def\posMultiplicity{below right}
								}
							}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{
										\def\posAttrName{above left}
										\def\posMultiplicity{below right}
									}{
										\def\posAttrName{above right}
										\def\posMultiplicity{below left}
									}
								}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{
										\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{
											\def\posAttrName{above right}
											\def\posMultiplicity{below left}
										}{
											\def\posAttrName{above left}
											\def\posMultiplicity{below right}
										}
									}{
										\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{
											\def\posAttrName{above left}
											\def\posMultiplicity{below right}
										}{
											\def\posAttrName{above right}
											\def\posMultiplicity{below left}
										}
									}
								}
							}
						}{}

						\ifthenelse{\thepos=200}{
							\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{
									\def\posAttrName{above left}
									\def\posMultiplicity{below right}
								}{
									\def\posAttrName{above right}
									\def\posMultiplicity{below left}
								}
							}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{
										\def\posAttrName{above right}
										\def\posMultiplicity{below left}
									}{
										\def\posAttrName{above left}
										\def\posMultiplicity{below right}
									}
								}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{
										\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{
											\def\posAttrName{above left}
											\def\posMultiplicity{below right}
										}{
											\def\posAttrName{above right}
											\def\posMultiplicity{below left}
										}
									}{
										\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{
											\def\posAttrName{above right}
											\def\posMultiplicity{below left}
										}{
											\def\posAttrName{above left}
											\def\posMultiplicity{below right}
										}
									}
								}
							}
						}{}

						\ifnum\thepos>300
							\pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-300)/100}
							\xdef\tikzumlLastArc{\tikzumlLastArc
								node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
								node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
							}
						\else
							\ifnum\thepos<100
								\xdef\tikzumlFirstArc{\tikzumlFirstArc
									node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
									node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
								}
							\else
								\ifnum\thepos>200
									\pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100}
									\xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc
										node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
										node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
									}
								\else
									\pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100}
									\xdef\tikzumlMidOneArc{\tikzumlMidOneArc
										node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
										node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
									}
								\fi
							\fi
						\fi

						\ifthenelse{\theposT=300\OR\theposT=100}{
							\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{
									\def\posAttrNameT{above right}
									\def\posMultiplicityT{below left}
								}{
									\def\posAttrNameT{above left}
									\def\posMultiplicityT{below right}
								}
							}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{
										\def\posAttrNameT{above left}
										\def\posMultiplicityT{below right}
									}{
										\def\posAttrNameT{above right}
										\def\posMultiplicityT{below left}
									}
								}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{
										\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{
											\def\posAttrNameT{above right}
											\def\posMultiplicityT{below left}
										}{
											\def\posAttrNameT{above left}
											\def\posMultiplicityT{below right}
										}
									}{
										\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{
											\def\posAttrNameT{above left}
											\def\posMultiplicityT{below right}
										}{
											\def\posAttrNameT{above right}
											\def\posMultiplicityT{below left}
										}
									}
								}
							}
						}{}
						\ifthenelse{\theposT=200}{
							\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{
									\def\posAttrNameT{above left}
									\def\posMultiplicity{below right}
								}{
									\def\posAttrNameT{above right}
									\def\posMultiplicityT{below left}
								}
							}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{
										\def\posAttrNameT{above right}
										\def\posMultiplicityT{below left}
									}{
										\def\posAttrNameT{above left}
										\def\posMultiplicityT{below right}
									}
								}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{
										\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{
											\def\posAttrNameT{above left}
											\def\posMultiplicityT{below right}
										}{
											\def\posAttrNameT{above right}
											\def\posMultiplicityT{below left}
										}
									}{
										\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{
											\def\posAttrNameT{above right}
											\def\posMultiplicityT{below left}
										}{
											\def\posAttrNameT{above left}
											\def\posMultiplicityT{below right}
										}
									}
								}
							}
						}{}

						\ifnum\theposT>300
							\pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-300)/100}
							\xdef\tikzumlLastArc{\tikzumlLastArc
								node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
								node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
							}
						\else
							\ifnum\theposT<100
								\xdef\tikzumlFirstArc{\tikzumlFirstArc
									node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
									node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
								}
							\else
								\ifnum\theposT>200
									\pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100}
									\xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc
										node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
										node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
									}
								\else
									\pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100}
									\xdef\tikzumlMidOneArc{\tikzumlMidOneArc
										node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
										node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
									}
								\fi
							\fi
						\fi
					\else
						\ifnum\theposStereo>200
							\pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100}
							\xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
						\else
							\ifnum\theposStereo<100
								\xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
							\else
								\pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}
								\xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
							\fi
						\fi

						\ifthenelse{\thepos=100}{
							\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{
								\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
									\def\posAttrName{above right}
									\def\posMultiplicity{below left}
								}{
									\def\posAttrName{above left}
									\def\posMultiplicity{below right}
								}
							}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{
									\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
										\def\posAttrName{above left}
										\def\posMultiplicity{below right}
									}{
										\def\posAttrName{above right}
										\def\posMultiplicity{below left}
									}
								}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{
										\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
											\def\posAttrName{above right}
											\def\posMultiplicity{below left}
										}{
											\def\posAttrName{above left}
											\def\posMultiplicity{below right}
										}
									}{
										\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
											\def\posAttrName{above left}
											\def\posMultiplicity{below right}
										}{
											\def\posAttrName{above right}
											\def\posMultiplicity{below left}
										}
									}
								}
							}
						}{}

						\ifthenelse{\thepos=200}{
							\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{
								\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
									\def\posAttrName{above left}
									\def\posMultiplicity{below right}
								}{
									\def\posAttrName{above right}
									\def\posMultiplicity{below left}
								}
							}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{
									\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
										\def\posAttrName{above right}
										\def\posMultiplicity{below left}
									}{
										\def\posAttrName{above left}
										\def\posMultiplicity{below right}
									}
								}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{
										\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
											\def\posAttrName{above left}
											\def\posMultiplicity{below right}
										}{
											\def\posAttrName{above right}
											\def\posMultiplicity{below left}
										}
									}{
										\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
											\def\posAttrName{above right}
											\def\posMultiplicity{below left}
										}{
											\def\posAttrName{above left}
											\def\posMultiplicity{below right}
										}
									}
								}
							}
						}{}

						\ifnum\thepos>200
							\pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100}
							\xdef\tikzumlLastArc{\tikzumlLastArc
								node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
								node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
							}
						\else
							\ifnum\thepos<100
								\xdef\tikzumlFirstArc{\tikzumlFirstArc
									node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
									node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
								}
							\else
								\pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100}
								\xdef\tikzumlMidOneArc{\tikzumlMidOneArc
									node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
									node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
								}
							\fi
						\fi

						\ifthenelse{\theposT=100}{
							\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{
								\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
									\def\posAttrNameT{above right}
									\def\posMultiplicityT{below left}
								}{
									\def\posAttrNameT{above left}
									\def\posMultiplicityT{below right}
								}
							}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{
									\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
										\def\posAttrNameT{above left}
										\def\posMultiplicityT{below right}
									}{
										\def\posAttrNameT{above right}
										\def\posMultiplicityT{below left}
									}
								}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{
										\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
											\def\posAttrNameT{above right}
											\def\posMultiplicityT{below left}
										}{
											\def\posAttrNameT{above left}
											\def\posMultiplicityT{below right}
										}
									}{
										\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
											\def\posAttrNameT{above left}
											\def\posMultiplicityT{below right}
										}{
											\def\posAttrNameT{above right}
											\def\posMultiplicityT{below left}
										}
									}
								}
							}
						}{}

						\ifthenelse{\theposT=200}{
							\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{
								\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
									\def\posAttrNameT{above left}
									\def\posMultiplicityT{below right}
								}{
									\def\posAttrNameT{above right}
									\def\posMultiplicityT{below left}
								}
							}{
								\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{
									\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
										\def\posAttrNameT{above right}
										\def\posMultiplicityT{below left}
									}{
										\def\posAttrNameT{above left}
										\def\posMultiplicityT{below right}
									}
								}{
									\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{
										\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
											\def\posAttrNameT{above left}
											\def\posMultiplicityT{below right}
										}{
											\def\posAttrNameT{above right}
											\def\posMultiplicityT{below left}
										}
									}{
										\ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{
											\def\posAttrNameT{above right}
											\def\posMultiplicityT{below left}
										}{
											\def\posAttrNameT{above left}
											\def\posMultiplicityT{below right}
										}
									}
								}
							}
						}{}

						\ifnum\theposT>200
							\pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100}
							\xdef\tikzumlLastArc{\tikzumlLastArc
								node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
								node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
							}
						\else
							\ifnum\theposT<100
								\xdef\tikzumlFirstArc{\tikzumlFirstArc
									node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
									node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
								}
							\else
								\pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100}
								\xdef\tikzumlMidOneArc{\tikzumlMidOneArc
									node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
									node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
								}
							\fi
						\fi
					\fi

					\ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{\tikzumlRelationRecursiveDirectionEnd}}{
						\xdef\tikzumlPath{(\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle) -- \tikzumlFirstArc (\tikzumlRelationName-2.center) -- \tikzumlMidOneArc (\tikzumlRelationName-4.center) -- \tikzumlLastArc (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle) }
						\ifnum\thetikzumlStateLevel>0
							\def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}
							\expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5)}
						\fi
					}{
						\xdef\tikzumlPath{(\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle) -- \tikzumlFirstArc (\tikzumlRelationName-2.center) -- \tikzumlMidOneArc (\tikzumlRelationName-4.center) -- \tikzumlMidTwoArc (\tikzumlRelationName-6.center) -- \tikzumlLastArc (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle) }
						\ifnum\thetikzumlStateLevel>0
							\def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}
							\expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5) (\tikzumlRelationName-6) (\tikzumlRelationName-7)}
						\fi
					}
				}{}
			}
		}{
			\def\arcNum{1}
			\def\arcNumT{1}

			\node[inner sep=0] (\tikzumlRelationName-1) at (\tikzumlRelationName-middle) {};
			\xdef\tikzumlLastArc{
				node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
				node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
				node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
				node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
				node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype}
			}
			\xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) }
			\ifnum\thetikzumlStateLevel>0
				\def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}
				\expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) }
			\fi
		}
	}{
		% first vertical then horizontal line
		\ifthenelse{\equal{\tikzumlRelationGeometry}{|-}}
		{
			%\setcounter{tikzumlControlNodesNum}{1}

			\def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} }
			\def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-3, anchor=center]{} }

			\begin{pgfonlayer}{connections}
			\node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor |- \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};
			\end{pgfonlayer}

			\ifnum\theposStereo>100
				\pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}
				\xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
			\else
				\xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
			\fi

			\ifnum\thepos>100
				\pgfmathsetmacro{\tikzumlRelationPosition}{(\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=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
					node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
				}
			\fi
			\ifnum\arcNum=2
				\xdef\tikzumlLastArc{\tikzumlLastArc
					node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
					node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
				}
			\fi

			\ifnum\theposT>100
				\pgfmathsetmacro{\tikzumlRelationPositionT}{(\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=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
					node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
				}
			\fi
			\ifnum\arcNumT=2
				\xdef\tikzumlLastArc{\tikzumlLastArc
					node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
					node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
				}
			\fi

			\xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) }
			\ifnum\thetikzumlStateLevel>0
				\def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}
				\expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) }
			\fi
		}{
			% first horizontal then vertical line
			\ifthenelse{\equal{\tikzumlRelationGeometry}{-|}}
			{
				%\setcounter{tikzumlControlNodesNum}{1}

				\def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center]{} }
				\def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-3, anchor=center] {} }

				\begin{pgfonlayer}{connections}
				\node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor -| \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};
				\end{pgfonlayer}

				\ifnum\theposStereo>100
					\pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}
					\xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
				\else
					\xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
				\fi

				\ifnum\thepos>100
					\pgfmathsetmacro{\tikzumlRelationPosition}{(\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=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
						node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
					}
				\fi
				\ifnum\arcNum=2
					\xdef\tikzumlLastArc{\tikzumlLastArc
						node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
						node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
					}
				\fi

				\ifnum\theposT>100
					\pgfmathsetmacro{\tikzumlRelationPositionT}{(\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=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
						node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
					}
				\fi
				\ifnum\arcNumT=2
					\xdef\tikzumlLastArc{\tikzumlLastArc
						node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
						node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
					}
				\fi

				\xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) }
				\ifnum\thetikzumlStateLevel>0
					\def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}
					\expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) }
				\fi
			}{
				% first vertical, then horizontal, finally vertical line
				\ifthenelse{\equal{\tikzumlRelationGeometry}{|-|}}
				{
					%\setcounter{tikzumlControlNodesNum}{2}

					\def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} }
					\def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {} }
					\def\tikzumlMidOneArc{ }

					\begin{pgfonlayer}{connections}

					\ifthenelse{\equal{\tikzumlRelationArmO}{auto}}{
						\ifthenelse{\equal{\tikzumlRelationArmT}{auto}}{
							\node[inner sep=0] (\tikzumlRelationName-3) at (\tikzumlRelationName-middle) {};
							\node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor |- \tikzumlRelationName-3) {};
							\node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-3 -| \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};
						}{
							\draw (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor)+(0,\tikzumlRelationArmT) node[inner sep=0, name=\tikzumlRelationName-4] {};
							\node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlRelationName-4 -| \tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) {};
							\node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {};
						}
					}{
						\draw (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor)+(0,\tikzumlRelationArmO) node[inner sep=0, name=\tikzumlRelationName-2] {};
						\node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-2 -| \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};
						\node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {};
					}
					\end{pgfonlayer}

					\ifnum\theposStereo>200
						\pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100}
						\xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
					\else
						\ifnum\theposStereo<100
							\xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
						\else
							\pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}
							\xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
						\fi
					\fi

					\ifthenelse{\thepos=200\OR\thepos=100}{
						\def\posAttrName{above left}
						\def\posMultiplicity{below right}
					}{}

					\ifthenelse{\thepos>200}{
						\pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100}
						\def\arcNum{3}
					}{
						\ifthenelse{\thepos<100}{
							\def\arcNum{1}
						}{
							\pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100}
							\def\arcNum{2}
						}
					}

					\ifnum\arcNum=1
						\xdef\tikzumlFirstArc{\tikzumlFirstArc
							node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
							node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
						}
					\fi
					\ifnum\arcNum=2
						\xdef\tikzumlMidOneArc{\tikzumlMidOneArc
							node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
							node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
						}
					\fi
					\ifnum\arcNum=3
						\xdef\tikzumlLastArc{\tikzumlLastArc
							node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
							node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
						}
					\fi

					\ifthenelse{\theposT=200\OR\theposT=100}{
						\def\posAttrNameT{above left}
						\def\posMultiplicityT{below right}
					}{}

					\ifthenelse{\theposT>200}{
						\pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100}
						\def\arcNumT{3}
					}{
						\ifthenelse{\theposT<100}{
							\def\arcNumT{1}
						}{
							\pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100}
							\def\arcNumT{2}
						}
					}

					\ifnum\arcNumT=1
						\xdef\tikzumlFirstArc{\tikzumlFirstArc
							node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
							node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
						}
					\fi
					\ifnum\arcNumT=2
						\xdef\tikzumlMidOneArc{\tikzumlMidOneArc
							node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
							node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
						}
					\fi
					\ifnum\arcNumT=3
						\xdef\tikzumlLastArc{\tikzumlLastArc
							node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
							node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
						}
					\fi

					\xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlMidOneArc (\tikzumlRelationName-4.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) }
					\ifnum\thetikzumlStateLevel>0
						\def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}
						\expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5) }
					\fi
				}{
					% first horizontal, then vertical, finally horizontal line
					\ifthenelse{\equal{\tikzumlRelationGeometry}{-|-}}
					{
						%\setcounter{tikzumlControlNodesNum}{2}

						\def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} }
						\def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {} }
						\def\tikzumlMidOneArc{}

						\begin{pgfonlayer}{connections}

						\ifthenelse{\equal{\tikzumlRelationArmO}{auto}}{
							\ifthenelse{\equal{\tikzumlRelationArmT}{auto}}{
								\node[inner sep=0] (\tikzumlRelationName-3) at (\tikzumlRelationName-middle) {};
								\node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor -| \tikzumlRelationName-3) {};
								\node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-3 |- \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};
							}{
								\draw (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor)+(\tikzumlRelationArmT,0) node[inner sep=0, name=\tikzumlRelationName-4] {};
								\node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlRelationName-4 |- \tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) {};
								\node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {};
							}
						}{
							\draw (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor)+(\tikzumlRelationArmO,0) node[inner sep=0, name=\tikzumlRelationName-2] {};
							\node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-2 |- \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};
							\node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {};
						}
						\end{pgfonlayer}

						\ifnum\theposStereo>200
							\pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100}
							\xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
						\else
							\ifnum\theposStereo<100
								\xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
							\else
								\pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}
								\xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} }
							\fi
						\fi

						\ifthenelse{\thepos=200\OR\thepos=100}{
							\def\posAttrName{above left}
							\def\posMultiplicity{below right}
						}{}

						\ifthenelse{\thepos>200}{
							\pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100}
							\def\arcNum{3}
						}{
							\ifthenelse{\thepos<100}{
								\def\arcNum{1}
							}{
								\pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100}
								\def\arcNum{2}
							}
						}

						\ifnum\arcNum=1
							\xdef\tikzumlFirstArc{\tikzumlFirstArc
								node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
								node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
							}
						\fi
						\ifnum\arcNum=2
							\xdef\tikzumlMidOneArc{\tikzumlMidOneArc
								node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
								node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
							}
						\fi
						\ifnum\arcNum=3
							\xdef\tikzumlLastArc{\tikzumlLastArc
								node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}
								node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}
							}
						\fi

						\ifthenelse{\theposT=200\OR\theposT=100}{
							\def\posAttrNameT{above left}
							\def\posMultiplicityT{below right}
						}{}

						\ifthenelse{\theposT>200}{
							\pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100}
							\def\arcNumT{3}
						}{
							\ifthenelse{\theposT<100}{
								\def\arcNumT{1}
							}{
								\pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100}
								\def\arcNumT{2}
							}
						}

						\ifnum\arcNumT=1
							\xdef\tikzumlFirstArc{\tikzumlFirstArc
								node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
								node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
							}
						\fi
						\ifnum\arcNumT=2
							\xdef\tikzumlMidOneArc{\tikzumlMidOneArc
								node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
								node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
							}
						\fi
						\ifnum\arcNumT=3
							\xdef\tikzumlLastArc{\tikzumlLastArc
								node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}
								node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}
							}
						\fi

						\xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlMidOneArc (\tikzumlRelationName-4.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) }
						\ifnum\thetikzumlStateLevel>0
							\def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}
							\expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5) }
						\fi
					}{
						\errmessage{TIKZUML ERROR : Unknown geometry value !!! It should be in the following list : --, |-, -|, |-|, -|-}
					}
				}
			}
		}
	}

	\begin{pgfonlayer}{connections}
	\ifthenelse{\equal{\tikzumlRelationStyle}{tikzuml nesting style}}{
		\pgfarrowsdeclare{nested}{nested}{}
		{
			\tikzumlNestingSymbolSize=0.2pt
			\advance\tikzumlNestingSymbolSize by .5\pgflinewidth
			\pgfsetdash{}{0pt} %  do not dash
			\pgfsetroundjoin   %  fix join
			\pgfsetroundcap    %  fix cap
			\pgfpathmoveto{\pgfpoint{-16*\tikzumlNestingSymbolSize}{0pt}}
			\pgfpatharc{180}{90}{8*\tikzumlNestingSymbolSize}
			\pgfpatharc{90}{0}{8*\tikzumlNestingSymbolSize}
			\pgfpatharc{0}{-90}{8*\tikzumlNestingSymbolSize}
			\pgfpatharc{-90}{-180}{8*\tikzumlNestingSymbolSize}
			\pgfpathmoveto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{8*\tikzumlNestingSymbolSize}}
			\pgfpathlineto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{-8*\tikzumlNestingSymbolSize}}
			\pgfusepathqstroke
		}
		\draw[auto, nested-, font=\tikzumlDefaultFont, \tikzumlRelationStyle, /tikzuml/relation/style2] \tikzumlPath ;
	}{
		\draw[auto, font=\tikzumlDefaultFont, \tikzumlRelationStyle, /tikzuml/relation/style2] \tikzumlPath ;
	}
	\end{pgfonlayer}

	\stepcounter{tikzumlRelationNum}
}

% shortcuts of \umlrelation
\newcommand{\umlHVrelation}[3][]{
	\pgfkeys{/tikzuml/HVrelation/.cd,
	.unknown/.code={
		\let\keyname=\pgfkeyscurrentname
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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{\umlcompos}[3][]{\umlrelation[style={tikzuml composition style}, #1]{#2}{#3}}
\newcommand{\umlunicompos}[3][]{\umlrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}
\newcommand{\umlimport}[3][]{\umlrelation[style={tikzuml import style}, #1]{#2}{#3}}
\newcommand{\umlnest}[3][]{\umlrelation[style={tikzuml nesting 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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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{\umlHVcompos}[3][]{\umlHVrelation[style={tikzuml composition style}, #1]{#2}{#3}}
\newcommand{\umlHVunicompos}[3][]{\umlHVrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}
\newcommand{\umlHVimport}[3][]{\umlHVrelation[style={tikzuml import style}, #1]{#2}{#3}}
\newcommand{\umlHVnest}[3][]{\umlHVrelation[style={tikzuml nesting 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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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{\umlVHcompos}[3][]{\umlVHrelation[style={tikzuml composition style}, #1]{#2}{#3}}
\newcommand{\umlVHunicompos}[3][]{\umlVHrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}
\newcommand{\umlVHimport}[3][]{\umlVHrelation[style={tikzuml import style}, #1]{#2}{#3}}
\newcommand{\umlVHnest}[3][]{\umlVHrelation[style={tikzuml nesting 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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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{\umlHVHcompos}[3][]{\umlHVHrelation[style={tikzuml composition style}, #1]{#2}{#3}}
\newcommand{\umlHVHunicompos}[3][]{\umlHVHrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}
\newcommand{\umlHVHimport}[3][]{\umlHVHrelation[style={tikzuml import style}, #1]{#2}{#3}}
\newcommand{\umlHVHnest}[3][]{\umlHVHrelation[style={tikzuml nesting 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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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{\umlVHVcompos}[3][]{\umlVHVrelation[style={tikzuml composition style}, #1]{#2}{#3}}
\newcommand{\umlVHVunicompos}[3][]{\umlVHVrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}
\newcommand{\umlVHVimport}[3][]{\umlVHVrelation[style={tikzuml import style}, #1]{#2}{#3}}
\newcommand{\umlVHVnest}[3][]{\umlVHVrelation[style={tikzuml nesting 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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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 : arg1, arg2, arg: name of the src/dest/dest side class type attribute defined by the relation
%            mult1, mult2, mult: multiplicity of the src/dest/dest side class type attribute defined by the relation
%            pos1, pos2, pos: position of the src/dest/dest side class type attribute defined by the relation
%            align1, align2, align: text justification of the src/dest/dest side class type attribute defined by the relation
%            anchor1, anchor2: src/dest anchors on linked classes
%            stereo: stereotype of the relation
%            st:pos, st:anchor, st:fill: stereotype position, anchor, and background
%            style: style of the relation (association, aggregation, composition, inherit, ...)
%            name: rootname used for naming nodes of the relation
\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={}, st:pos/.initial=1,
		st:anchor/.initial=center, st:fill/.initial=none,
		style/.initial=->, name/.initial=relation-\thetikzumlRelationNum,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\errmessage{TIKZUML ERROR : in umlCNrelation, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/relation/.cd,#1}
	\pgfkeys{/tikzuml/relation/.cd, arg1/.get=\tikzumlCNRelationAttrName, arg2/.get=\tikzumlCNRelationAttrNameTO, arg/.get=\tikzumlCNRelationAttrNameTT,
		mult1/.get=\tikzumlCNRelationMultiplicity, mult2/.get=\tikzumlCNRelationMultiplicityTO, mult/.get=\tikzumlCNRelationMultiplicityTT,
		pos1/.get=\tikzumlCNRelationPosition, pos2/.get=\tikzumlCNRelationPositionTO, pos/.get=\tikzumlCNRelationPositionTT,
		align1/.get=\tikzumlCNRelationAlign, align2/.get=\tikzumlCNRelationAlignTO, align/.get=\tikzumlCNRelationAlignTT,
		anchor1/.get=\tikzumlCNRelationSrcAnchor, anchor2/.get=\tikzumlCNRelationDestAnchor,
		stereo/.get=\tikzumlCNRelationStereoType, st:pos/.get=\tikzumlCNRelationPositionStereotype,
		st:anchor/.get=\tikzumlCNRelationStereotypeAnchor,
		st:fill/.get=\tikzumlCNRelationStereotypeFill,
		style/.get=\tikzumlCNRelationStyle, name/.get=\tikzumlCNRelationName
	}

	% managing \_ in class names for node names
	\def\tikzumlSrcClassName{#2}
	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlSrcClassNodeName{\tikzumlSrcClassName}}\x

	\StrSubstitute{\tikzumlSrcClassNodeName}{:}{@COLON@}[\tikzumlSrcClassNodeName]
	\StrSubstitute{\tikzumlSrcClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlSrcClassNodeName]

	\def\tikzumlDestClassName{#4}
	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlDestClassNodeName{\tikzumlDestClassName}}\x

	\StrSubstitute{\tikzumlDestClassNodeName}{:}{@COLON@}[\tikzumlDestClassNodeName]
	\StrSubstitute{\tikzumlDestClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlDestClassNodeName]

	% managing alias keys
	\def\tikzumlCNRelationAttrNameT{\tikzumlCNRelationAttrNameTO\tikzumlCNRelationAttrNameTT}
	\def\tikzumlCNRelationMultiplicityT{\tikzumlCNRelationMultiplicityTO\tikzumlCNRelationMultiplicityTT}
	\def\tikzumlCNRelationAlignT{\tikzumlCNRelationAlignTO\tikzumlCNRelationAlignTT}
	\def\orientationT{\orientationTO\orientationTT}

	\ifthenelse{\equal{\tikzumlCNRelationPositionTT}{tikzumlEmpty}}{
		\def\tikzumlCNRelationPositionT{\tikzumlCNRelationPositionTO}
	}{
		\def\tikzumlCNRelationPositionT{\tikzumlCNRelationPositionTT}
	}

	\def\attrAlign{}
	\def\multAlign{}
	\def\attrAlignT{}
	\def\multAlignT{}

	\ifthenelse{\equal{\tikzumlCNRelationAlign}{left}}{
		\def\attrAlign{above right}
		\def\multAlign{below right}
	}{
		\ifthenelse{\equal{\tikzumlCNRelationAlign}{right}}{
			\def\attrAlign{above left}
			\def\multAlign{below left}
		}{}
	}

	\ifthenelse{\equal{\tikzumlCNRelationAlignT}{left}}{
		\def\attrAlignT{above right}
		\def\multAlignT{below right}
	}{
		\ifthenelse{\equal{\tikzumlCNRelationAlignT}{right}}{
			\def\attrAlignT{above left}
			\def\multAlignT{below left}
		}{}
	}

	% def stereotype
	\ifthenelse{\equal{\tikzumlCNRelationStereoType}{}}{
		\def\stereotype{}
	}{
		\def\stereotype{$\ll$\tikzumlCNRelationStereoType$\gg$}
	}

	% def anchors macros
	\ifthenelse{\equal{\tikzumlCNRelationSrcAnchor}{tikzumlEmpty}}{
		\def\tikzumlCNRelationSrcAnchor{}
	}{
		\let\tikzumlCNRelationSrcAnchorold\tikzumlCNRelationSrcAnchor
		\def\tikzumlCNRelationSrcAnchor{.\tikzumlCNRelationSrcAnchorold}
	}

	\ifthenelse{\equal{\tikzumlCNRelationDestAnchor}{tikzumlEmpty}}{
		\def\tikzumlCNRelationDestAnchor{}
	}{
		\let\tikzumlCNRelationDestAnchorold\tikzumlCNRelationDestAnchor
		\def\tikzumlCNRelationDestAnchor{.\tikzumlCNRelationDestAnchorold}
	}

	\setcounter{pos}{100*\real{\tikzumlCNRelationPosition}}
	\setcounter{posT}{100*\real{\tikzumlCNRelationPositionT}}
	\setcounter{posStereo}{100*\real{\tikzumlCNRelationPositionStereotype}}

	% straight line
	%\setcounter{tikzumlControlNodesNum}{1}

	\def\tikzumlFirstArc{node[midway, name=\tikzumlCNRelationName-1, anchor=center] {} }
	\def\tikzumlLastArc{node[midway, name=\tikzumlCNRelationName-3, anchor=center]{} }
	\def\posAttrName{}
	\def\posMultiplicity{}
	\def\posAttrNameT{}
	\def\posMultiplicityT{}

	\begin{pgfonlayer}{connections}
	\node (\tikzumlCNRelationName-2) at (#3) {};
	\end{pgfonlayer}

	\ifnum\theposStereo>100
		\pgfmathsetmacro{\tikzumlCNRelationPositionStereotype}{(\theposStereo-100)/100}
		\xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlCNRelationPositionStereotype, anchor=\tikzumlCNRelationStereotypeAnchor, fill=\tikzumlCNRelationStereotypeFill] {\stereotype} }
	\else
		\xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlCNRelationPositionStereotype, anchor=\tikzumlCNRelationStereotypeAnchor, fill=\tikzumlCNRelationStereotypeFill] {\stereotype} }
	\fi

	\ifnum\thepos>100
		\pgfmathsetmacro{\tikzumlCNRelationPosition}{(\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=\tikzumlCNRelationPosition, \posAttrName, \attrAlign] {\tikzumlCNRelationAttrName}
			node[pos=\tikzumlCNRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlCNRelationMultiplicity}
		}
	\fi
	\ifnum\arcNum=2
		\xdef\tikzumlLastArc{\tikzumlLastArc
			node[pos=\tikzumlCNRelationPosition, \posAttrName, \attrAlign] {\tikzumlCNRelationAttrName}
			node[pos=\tikzumlCNRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlCNRelationMultiplicity}
		}
	\fi

	\ifnum\theposT>100
		\pgfmathsetmacro{\tikzumlCNRelationPositionT}{(\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=\tikzumlCNRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlCNRelationAttrNameT}
			node[pos=\tikzumlCNRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlCNRelationMultiplicityT}
		}
	\fi
	\ifnum\arcNumT=2
		\xdef\tikzumlLastArc{\tikzumlLastArc
			node[pos=\tikzumlCNRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlCNRelationAttrNameT}
			node[pos=\tikzumlCNRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlCNRelationMultiplicityT}
		}
	\fi

	\xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlCNRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlCNRelationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlCNRelationDestAnchor) }

	\begin{pgfonlayer}{connections}
	\ifthenelse{\equal{\tikzumlCNRelationStyle}{tikzuml nesting style}}{
		\pgfarrowsdeclare{nested}{nested}{}
		{
			\tikzumlNestingSymbolSize=0.2pt
			\advance\tikzumlNestingSymbolSize by .5\pgflinewidth
			\pgfsetdash{}{0pt} %  do not dash
			\pgfsetroundjoin   %  fix join
			\pgfsetroundcap    %  fix cap
			\pgfpathmoveto{\pgfpoint{-16*\tikzumlNestingSymbolSize}{0pt}}
			\pgfpatharc{180}{90}{8*\tikzumlNestingSymbolSize}
			\pgfpatharc{90}{0}{8*\tikzumlNestingSymbolSize}
			\pgfpatharc{0}{-90}{8*\tikzumlNestingSymbolSize}
			\pgfpatharc{-90}{-180}{8*\tikzumlNestingSymbolSize}
			\pgfpathmoveto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{8*\tikzumlNestingSymbolSize}}
			\pgfpathlineto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{-8*\tikzumlNestingSymbolSize}}
			\pgfusepathqstroke
		}
		\draw[auto, \tikzumlCNRelationStyle, nested-, font=\tikzumlDefaultFont] \tikzumlPath ;
	}{
		\draw[auto, \tikzumlCNRelationStyle, font=\tikzumlDefaultFont] \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{\umlCNcompos}[4][]{\umlCNrelation[style={tikzuml composition style}, #1]{#2}{#3}{#4}}
\newcommand{\umlCNunicompos}[4][]{\umlCNrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}{#4}}
\newcommand{\umlCNimport}[4][]{\umlCNrelation[style={tikzuml import style}, #1]{#2}{#3}{#4}}
\newcommand{\umlCNnest}[4][]{\umlCNrelation[style={tikzuml nesting 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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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: width of the note
%            geometry: geometry of the relation between the note and what it is about
%            weight: barycentric weight for a 3-line relation
%            arm: length of the first arm
%            anchor1, anchor2: anchors of the relation
%            draw, fill, text: colors
%            style: to manage every default TikZ option
%            no coords: to tell that the note position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlnote}[3][]{
	\pgfkeys{/tikzuml/note/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlNoteDefaultWidth,
		geometry/.initial=\tikzumlRelationDefaultGeometry,
		weight/.initial=\tikzumlRelationDefaultWeight, arm/.initial=auto, style/.style={},
		anchor1/.initial=tikzumlEmpty, anchor2/.initial=tikzumlEmpty,
		draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlNoteDefaultFillColor,
		text/.initial=\tikzumlDefaultTextColor,
		no coords/.is if=tikzumlnoteWithoutCoords,
		no coords=false,
		px/.initial=0, py/.initial=0,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/note/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/note/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/note/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\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=\tikzumlNoteTextWidth,
		geometry/.get=\tikzumlNoteGeometry,
		weight/.get=\tikzumlNoteWeight, arm/.get=\tikzumlNoteArm,
		anchor1/.get=\tikzumlNoteSrcAnchor, anchor2/.get=\tikzumlNoteDestAnchor,
		draw/.get=\tikzumlNoteDrawColor, fill/.get=\tikzumlNoteFillColor,
		text/.get=\tikzumlNoteTextColor,
		px/.get=\tikzumlNotePointerX, py/.get=\tikzumlNotePointerY,
	}

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

	\iftikzumlnoteWithoutCoords
		\node[text=\tikzumlNoteTextColor, text width=\tikzumlNoteTextWidth, font=\tikzumlDefaultFont, outer sep=0, inner xsep=1ex, inner ysep=3ex, /tikzuml/note/style] (note-\thetikzumlNoteNum-coord) {#3};
	\else
		\node[text=\tikzumlNoteTextColor, text width=\tikzumlNoteTextWidth, font=\tikzumlDefaultFont, outer sep=0, inner xsep=1ex, inner ysep=3ex, /tikzuml/note/style] (note-\thetikzumlNoteNum-coord) at (\tikzumlNoteX, \tikzumlNoteY) {#3};
	\fi
	\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=\tikzumlNoteDrawColor, fill=\tikzumlNoteFillColor] (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=\tikzumlNoteTextColor, text width=\tikzumlNoteTextWidth, outer sep=0, inner xsep=1ex, inner ysep=3ex, font=\tikzumlDefaultFont] (note-\thetikzumlNoteNum) at (note-\thetikzumlNoteNum-coord) {#3};
	\draw[draw=\tikzumlNoteDrawColor] (note-\thetikzumlNoteNum-right-top) -| (note-\thetikzumlNoteNum-top-right);

	\pgfmathsetmacro{\tikzumlNoteWeightT}{1.0-\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 : --, |-, -|, |-|, -|-}
			}
		}
	}

	\ifthenelse{\equal{\tikzumlNotePointerX}{0}\AND\equal{\tikzumlNotePointerY}{0}}{
		\begin{pgfonlayer}{connections}
			\draw[densely dashed] (note-\thetikzumlNoteNum-coord\tikzumlNoteSrcAnchor) \tikzumlnotepath (\tikzumlClassNodeName\tikzumlNoteDestAnchor);
		\end{pgfonlayer}
	}{
		\begin{pgfonlayer}{main}
			\draw ([shift={(\tikzumlNotePointerX,\tikzumlNotePointerY)}]\tikzumlClassNodeName) node[circle,inner sep=3pt,fill=\tikzumlNoteFillColor,draw=\tikzumlNoteDrawColor] (note-\thetikzumlNoteNum-pointer) {};
			\draw[densely dashed] (note-\thetikzumlNoteNum-coord\tikzumlNoteSrcAnchor) \tikzumlnotepath (note-\thetikzumlNoteNum-pointer);
		\end{pgfonlayer}
	}


	\stepcounter{tikzumlNoteNum}
}

% shortcuts for note with geometry
\newcommand{\umlHVnote}[3][]{
	\pgfkeys{/tikzuml/note/.cd,
	.unknown/.code={
		\let\keyname=\pgfkeyscurrentname
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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: width of the class node
%            type: type of of class (class, interface, typedef, enum)
%            template: template parameters
%            name: name of the class node
%            geometry: geometry of the line
%            weight: barycentric weight of the middle part when geometry is a 3-line
%            arm: length of first part when geometry id a 3-line
%            anchor1, anchor2: src/dest anchors on linked classes
%            style: style of the association class (association, aggregation, composition, inherit, ...)
%            draw, fill, fill template, text: colors
%            style: to manage every default TikZ option
%            no coords: to tell that the class position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlassocclass}[5][]{
	\pgfkeys{/tikzuml/assocclass/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX,
		width/.initial=\tikzumlClassDefaultWidth, type/.initial=\tikzumlClassDefaultType, style/.style={},
		template/.initial={}, name/.initial=tikzumlEmpty, geometry/.initial=\tikzumlRelationDefaultGeometry,
		weight/.initial=\tikzumlRelationDefaultWeight, arm/.initial=auto,
		anchor1/.initial=tikzumlEmpty, anchor2/.initial=tikzumlEmpty,
		draw/.initial=\tikzumlDefaultDrawColor,
		fill template/.initial=\tikzumlClassTemplateFillColorDefaultFillColor,
		fill/.initial=\tikzumlClassDefaultFillColor,
		text/.initial=\tikzumlDefaultTextColor,
		no coords/.is if=tikzumlassocclassWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/assocclass/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/assocclass/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/assocclass/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlassocclass, invalid option \keyname}
		}
	}

	\pgfkeys{/tikzuml/assocclass/.cd,#1}
	\pgfkeys{/tikzuml/assocclass/.cd, x/.get=\tikzumlAssocClassX, y/.get=\tikzumlAssocClassY,
		width/.get=\tikzumlAssocClassMinimumWidth, type/.get=\tikzumlAssocClassTypeTmp,
		template/.get=\tikzumlAssocClassTemplateParam,
		name/.get=\tikzumlAssocClassName, geometry/.get=\tikzumlAssocClassGeometry,
		weight/.get=\tikzumlAssocClassWeight, arm/.get=\tikzumlAssocClassArm,
		anchor1/.get=\tikzumlAssocClassSrcAnchor,
		anchor2/.get=\tikzumlAssocClassDestAnchor,
		draw/.get=\tikzumlAssocClassDrawColor, fill/.get=\tikzumlAssocClassFillColor,
		text/.get=\tikzumlAssocClassTextColor, fill template/.get=\tikzumlAssocClassTemplateFillColor
	}

	\ifthenelse{\equal{\tikzumlAssocClassTypeTmp}{class}\OR\equal{\tikzumlAssocClassTypeTmp}{abstract}}{
		\def\tikzumlAssocClassType{}
	}{
		\def\tikzumlAssocClassType{$\ll$\tikzumlAssocClassTypeTmp$\gg$ \\}
	}

	\ifthenelse{\equal{\tikzumlAssocClassTemplateParam}{}}{
		\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{\tikzumlAssocClassName}{tikzumlEmpty}}{}{
		\def\tikzumlAssocClassNodeName{\tikzumlAssocClassName}
	}

	\StrSubstitute{\tikzumlAssocClassNodeName}{:}{@COLON@}[\tikzumlAssocClassNodeName]
	\StrSubstitute{\tikzumlAssocClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlAssocClassNodeName]

	\ifthenelse{\equal{\tikzumlAssocClassTypeTmp}{abstract}}{
		\let\tikzumlAssocClassNameOld\tikzumlAssocClassName
		\def\tikzumlAssocClassName{{\it \tikzumlAssocClassNameOld}}
	}{}

	\def\tikzumlAssocClassPos{\tikzumlAssocClassX,\tikzumlAssocClassY}
	\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}
	}

	\iftikzumlassocclassWithoutCoords
		\node[tikzuml class style, draw=\tikzumlAssocClassDrawColor, fill=\tikzumlAssocClassFillColor, text=\tikzumlAssocClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlAssocClassMinimumWidth, /tikzuml/assocclass/style] (\tikzumlAssocClassNodeName) {\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}
		};
	\else
		\node[tikzuml class style, draw=\tikzumlAssocClassDrawColor, fill=\tikzumlAssocClassFillColor, text=\tikzumlAssocClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlAssocClassMinimumWidth, /tikzuml/assocclass/style] (\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}
		};
	\fi

	\ifthenelse{\equal{\tikzumlAssocClassTemplateParam}{}}{}{
		\draw (\tikzumlAssocClassNodeName.north east) node[tikzuml template style, name=\tikzumlAssocClassNodeName-template, draw=\tikzumlAssocClassDrawColor, fill=\tikzumlAssocClassTemplateFillColor, text=\tikzumlAssocClassTextColor, font=\tikzumlDefaultFont] {\tikzumlAssocClassTemplateParam};
	}

	\pgfmathsetmacro{\tikzumlAssocClassWeightT}{1.0-\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{\tikzumlAssocClassTemplateParam}{}}{
			\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}

\newif\iftikzumlusecaseWithoutCoords
\newif\iftikzumlactorWithoutCoords

% 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=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX,
		draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlSystemDefaultFillColor,
		text/.initial=\tikzumlDefaultTextColor,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\errmessage{TIKZUML ERROR : in umlsystem, invalid option \keyname}
		}
	}

	\pgfkeys{/tikzuml/system/.cd, #1}
	\pgfkeys{/tikzuml/system/.cd, x/.get=\tikzumlSystemXShift, y/.get=\tikzumlSystemYShift,
		draw/.get=\tikzumlSystemDrawColor, fill/.get=\tikzumlSystemFillColor,
		text/.get=\tikzumlSystemTextColor
	}

	\stepcounter{tikzumlSystemLevel}

	\begin{scope}[xshift=\tikzumlSystemXShift cm, yshift=\tikzumlSystemYShift 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=\tikzumlSystemTextColor, font=\tikzumlDefaultFont] (\tikzumlSystemName-caption-tmp) at (\tikzumlSystemName-tmp.north) {\tikzumlSystemName};
	\node[draw=\tikzumlSystemDrawColor, fill=\tikzumlSystemFillColor, text=\tikzumlSystemTextColor, font=\tikzumlDefaultFont, inner ysep=1em, inner xsep=2ex, fit = (\tikzumlSystemName-tmp) (\tikzumlSystemName-caption-tmp)] (\tikzumlSystemName) {};
	\node[text=\tikzumlSystemTextColor, font=\tikzumlDefaultFont] (\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: name of the node
%            width: node width
%            draw, fill, text: colors
%            style: to manage every default TikZ option
%            no coords: to tell that the use case position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlusecase}[2][]{
	\stepcounter{tikzumlUseCaseNum}
	\pgfkeys{/tikzuml/usecase/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=auto,
		name/.initial=usecase-\thetikzumlUseCaseNum,
		draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlUseCaseDefaultFillColor,
		text/.initial=\tikzumlDefaultTextColor, style/.style={},
		no coords/.is if=tikzumlusecaseWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/usecase/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/usecase/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/usecase/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlusecase, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/usecase/.cd, #1}
	\pgfkeys{/tikzuml/usecase/.cd, x/.get=\tikzumlUseCaseX, y/.get=\tikzumlUseCaseY, width/.get=\tikzumlUseCaseTextWidth,
		name/.get=\tikzumlUseCaseName,
		draw/.get=\tikzumlUseCaseDrawColor, fill/.get=\tikzumlUseCaseFillColor,
		text/.get=\tikzumlUseCaseTextColor
	}

	\def\tikzumlUseCaseText{#2}

	\def\tikzumlUseCasePos{\tikzumlUseCaseX,\tikzumlUseCaseY}

	\ifthenelse{\equal{\tikzumlUseCaseTextWidth}{auto}}{
		\iftikzumlusecaseWithoutCoords
			\node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, /tikzuml/usecase/style] (\tikzumlUseCaseName) {\tikzumlUseCaseText};
		\else
			\node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, /tikzuml/usecase/style] (\tikzumlUseCaseName) at (\tikzumlUseCasePos) {\tikzumlUseCaseText};
		\fi
	}{
		\iftikzumlusecaseWithoutCoords
			\node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, text width=\tikzumlUseCaseTextWidth, /tikzuml/usecase/style] (\tikzumlUseCaseName) {\tikzumlUseCaseText};
		\else
			\node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, text width=\tikzumlUseCaseTextWidth, /tikzuml/usecase/style] (\tikzumlUseCaseName) at (\tikzumlUseCasePos) {\tikzumlUseCaseText};
		\fi
	}

	% add to fit
	\ifnum\c@tikzumlSystemLevel>0
		\let\tikzumlSystemFitOld\tikzumlSystemFit
		\xdef\tikzumlSystemFit{\tikzumlSystemFitOld (\tikzumlUseCaseName)}
		\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=\tikzumlPicturedActorScale}%

	\begin{tikzpicture}[#1]
	\coordinate (head) at (0,5ex);
	\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=\tikzumlPicturedActorScale*0.3333ex, minimum size=\tikzumlPicturedActorScale*3ex, anchor=base] at (head) {};
	\end{tikzpicture}
}

% define an actor
% arg : var name
% optional : x, y: coordinates of the actor
%            scale: scale factor of the actor symbol
%            below: distance between the actor symbol and its name below
%            draw, text: colors
%            style: to manage every default TikZ option
%            no coords: to tell that the actor position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlactor}[2][]{
	\stepcounter{tikzumlActorNum}
	\pgfkeys{/tikzuml/actor/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, scale/.initial=1, below/.initial=\tikzumlActorDefaultBelow,
		draw/.initial=\tikzumlDefaultDrawColor,
		head/.initial=yellow!30,
		text/.initial=\tikzumlDefaultTextColor,
		style/.style={},
		no coords/.is if=tikzumlactorWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/actor/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/actor/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/actor/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlactor, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/actor/.cd, #1}
	\pgfkeys{/tikzuml/actor/.cd,
		x/.get=\tikzumlActorX, y/.get=\tikzumlActorY, scale/.get=\tikzumlActorScale,
		below/.get=\tikzumlActorBelow, draw/.get=\tikzumlActorDrawColor, head/.get=\tikzumlActorHeadColor, text/.get=\tikzumlActorTextColor
	}

	\def\tikzumlActorName{#2}
	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlActorNodeName{\tikzumlActorName}}\x

	\def\tikzumlActorPos{\tikzumlActorX,\tikzumlActorY}

	\iftikzumlactorWithoutCoords
		\node[tikzuml actor style, text=\tikzumlActorTextColor, font=\tikzumlDefaultFont, /tikzuml/actor/style] (\tikzumlActorNodeName) {\picturedactor{scale=\tikzumlActorScale, fill=\tikzumlActorHeadColor, draw=\tikzumlActorDrawColor, thick}};
	\else
		\node[tikzuml actor style, text=\tikzumlActorTextColor, font=\tikzumlDefaultFont, /tikzuml/actor/style] (\tikzumlActorNodeName) at (\tikzumlActorPos) {\picturedactor{scale=\tikzumlActorScale, fill=\tikzumlActorHeadColor, draw=\tikzumlActorDrawColor, thick}};
	\fi
	\node[text=\tikzumlActorTextColor, font=\tikzumlDefaultFont, below=\tikzumlActorScale*\tikzumlActorBelow] at (\tikzumlActorNodeName) {\tikzumlActorName};

}

% shortcuts for include and extend relation
\newcommand{\umlinclude}[3][]{
	\pgfkeys{/tikzuml/includerelation/.cd,
	.unknown/.code={
		\let\keyname=\pgfkeyscurrentname
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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=\tikzumlDefaultDrawColor, rounded corners, -{Straight Barb[scale=3.5,angle'=55]}]

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

\newif\iftikzumlstatejoinWithoutCoords
\newif\iftikzumlstatedecisionWithoutCoords
\newif\iftikzumlstateinitialWithoutCoords
\newif\iftikzumlstatefinalWithoutCoords
\newif\iftikzumlstateenterWithoutCoords
\newif\iftikzumlstateexitWithoutCoords
\newif\iftikzumlstateendWithoutCoords
\newif\iftikzumlstatehistoryWithoutCoords
\newif\iftikzumlstatedeephistoryWithoutCoords
\newif\iftikzumlstateWithoutCoords

% define a uml join state
% args : name of the state
% optional : x,y: coordinates of the state
%            width: width of the state node
%            name: name of the state node
%            color: color of the join symbol
%            style: to manage every default TikZ option
%            no coords: to tell that the state position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlstatejoin}[1][]{
	\pgfkeys{/tikzuml/statejoin/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateJoinDefaultWidth,
		name/.initial=statejoin-\thetikzumlStateJoinNum,
		color/.initial=\tikzumlDefaultDrawColor, style/.style={},
		no coords/.is if=tikzumlstatejoinWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/statejoin/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/statejoin/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/statejoin/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlstatejoin, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/statejoin/.cd, #1}
	\pgfkeys{/tikzuml/statejoin/.cd, x/.get=\tikzumlStateJoinX, y/.get=\tikzumlStateJoinY, width/.get=\tikzumlStateJoinMinimumWidth,
		name/.get=\tikzumlStateJoinName, color/.get=\tikzumlStateJoinColor
	}

	\def\tikzumlStateJoinPos{\tikzumlStateJoinX,\tikzumlStateJoinY}

	\iftikzumlstatejoinWithoutCoords
		\node[circle, minimum size=\tikzumlStateJoinMinimumWidth, draw=\tikzumlStateJoinColor, fill=\tikzumlStateJoinColor, /tikzuml/statejoin/style] (\tikzumlStateJoinName) {};
	\else
		\node[circle, minimum size=\tikzumlStateJoinMinimumWidth, draw=\tikzumlStateJoinColor, fill=\tikzumlStateJoinColor, /tikzuml/statejoin/style] (\tikzumlStateJoinName) at (\tikzumlStateJoinPos) {};
	\fi

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

% define a uml decision state
% args : name of the state
% optional : x,y: coordinates of the state
%            width: width of the state node
%            name: name of the state node
%            color: color of the join symbol
%            style: to manage every default TikZ option
%            no coords: to tell that the state position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlstatedecision}[1][]{
	\pgfkeys{/tikzuml/statedecision/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateDecisionDefaultWidth,
		name/.initial=statedecision-\thetikzumlStateDecisionNum,
		color/.initial=\tikzumlDefaultDrawColor, style/.style={},
		no coords/.is if=tikzumlstatedecisionWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/statedecision/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/statedecision/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/statedecision/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlstatedecision, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/statedecision/.cd, #1}
	\pgfkeys{/tikzuml/statedecision/.cd, x/.get=\tikzumlStateDecisionX, y/.get=\tikzumlStateDecisionY, width/.get=\tikzumlStateDecisionMinimumWidth,
		name/.get=\tikzumlStateDecisionName, color/.get=\tikzumlStateDecisionColor
	}

	\def\tikzumlStateDecisionPos{\tikzumlStateDecisionX,\tikzumlStateDecisionY}

	\iftikzumlstatedecisionWithoutCoords
		\node[rectangle, rotate=45, minimum size=\tikzumlStateDecisionMinimumWidth, draw=\tikzumlStateDecisionColor, /tikzuml/statedecision/style] (\tikzumlStateDecisionName) {};
	\else
		\node[rectangle, rotate=45, minimum size=\tikzumlStateDecisionMinimumWidth, draw=\tikzumlStateDecisionColor, /tikzuml/statedecision/style] (\tikzumlStateDecisionName) at (\tikzumlStateDecisionPos) {};
	\fi

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

% define a uml initial state
% args : name of the state
% optional : x,y: coordinates of the state
%            width: width of the state node
%            name: name of the state node
%            entry, do, exit: entry/do/exit action of the state
%            color: color of the join symbol
%            style: to manage every default TikZ option
%            no coords: to tell that the state position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlstateinitial}[1][]{
	\pgfkeys{/tikzuml/stateinitial/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateInitialDefaultWidth,
		name/.initial=stateinitial-\thetikzumlStateInitialNum,
		color/.initial=\tikzumlDefaultDrawColor, style/.style={},
		no coords/.is if=tikzumlstateinitialWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/stateinitial/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/stateinitial/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/stateinitial/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlstateinitial, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/stateinitial/.cd, #1}
	\pgfkeys{/tikzuml/stateinitial/.cd, x/.get=\tikzumlStateInitialX, y/.get=\tikzumlStateInitialY, width/.get=\tikzumlStateInitialMinimumWidth,
		name/.get=\tikzumlStateInitialName, color/.get=\tikzumlStateInitialColor
	}

	\def\tikzumlStateInitialPos{\tikzumlStateInitialX,\tikzumlStateInitialY}

	\iftikzumlstateinitialWithoutCoords
		\node[circle, minimum size=\tikzumlStateInitialMinimumWidth, fill=\tikzumlStateInitialColor, /tikzuml/stateinitial/style] (\tikzumlStateInitialName) {};
	\else
		\node[circle, minimum size=\tikzumlStateInitialMinimumWidth, fill=\tikzumlStateInitialColor, /tikzuml/stateinitial/style] (\tikzumlStateInitialName) at (\tikzumlStateInitialPos) {};
	\fi

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

% define a uml final state
% args : name of the state
% optional : x,y: coordinates of the state
%            width: width of the state node
%            name: name of the state node
%            color: color of the join symbol
%            style: to manage every default TikZ option
%            no coords: to tell that the state position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlstatefinal}[1][]{
	\pgfkeys{/tikzuml/statefinal/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateFinalDefaultWidth,
		name/.initial=statefinal-\thetikzumlStateFinalNum,
		color/.initial=\tikzumlDefaultDrawColor, style/.style={},
		no coords/.is if=tikzumlstatefinalWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/statefinal/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/statefinal/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/statefinal/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlstatefinal, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/statefinal/.cd, #1}
	\pgfkeys{/tikzuml/statefinal/.cd, x/.get=\tikzumlStateFinalX, y/.get=\tikzumlStateFinalY, width/.get=\tikzumlStateFinalMinimumWidth,
		name/.get=\tikzumlStateFinalName, color/.get=\tikzumlStateFinalColor
	}

	\def\tikzumlStateFinalPos{\tikzumlStateFinalX,\tikzumlStateFinalY}

	\iftikzumlstatefinalWithoutCoords
		\node[circle, minimum size=\tikzumlStateFinalMinimumWidth, draw=\tikzumlStateFinalColor, fill=\tikzumlStateFinalColor, double, double distance=0.1cm, /tikzuml/statefinal/style] (\tikzumlStateFinalName) {};
	\else
		\node[circle, minimum size=\tikzumlStateFinalMinimumWidth, draw=\tikzumlStateFinalColor, fill=\tikzumlStateFinalColor, double, double distance=0.1cm, /tikzuml/statefinal/style] (\tikzumlStateFinalName) at (\tikzumlStateFinalPos) {};
	\fi

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

% define a uml enter state
% args : name of the state
% optional : x,y: coordinates of the state
%            width: width of the state node
%            name: name of the state node
%            color: color of the join symbol
%            style: to manage every default TikZ option
%            no coords: to tell that the state position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlstateenter}[1][]{
	\pgfkeys{/tikzuml/stateenter/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateEnterDefaultWidth,
		name/.initial=stateenter-\thetikzumlStateEnterNum,
		color/.initial=\tikzumlDefaultDrawColor, style/.style={},
		no coords/.is if=tikzumlstateenterWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/stateenter/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/stateenter/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/stateenter/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlstateenter, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/stateenter/.cd, #1}
	\pgfkeys{/tikzuml/stateenter/.cd, x/.get=\tikzumlStateEnterX, y/.get=\tikzumlStateEnterY, width/.get=\tikzumlStateEnterMinimumWidth,
		name/.get=\tikzumlStateEnterName, color/.get=\tikzumlStateEnterColor
	}

	\def\tikzumlStateEnterPos{\tikzumlStateEnterX,\tikzumlStateEnterY}

	\iftikzumlstateenterWithoutCoords
		\node[circle, minimum size=\tikzumlStateEnterMinimumWidth, draw=\tikzumlStateEnterColor, /tikzuml/stateenter/style] (\tikzumlStateEnterName) {};
	\else
		\node[circle, minimum size=\tikzumlStateEnterMinimumWidth, draw=\tikzumlStateEnterColor, /tikzuml/stateenter/style] (\tikzumlStateEnterName) at (\tikzumlStateEnterPos) {};
	\fi

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

% define a uml exit state
% args : name of the state
% optional : x,y: coordinates of the state
%            width: width of the state node
%            name: name of the state node
%            color: color of the join symbol
%            style: to manage every default TikZ option
%            no coords: to tell that the state position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlstateexit}[1][]{
	\pgfkeys{/tikzuml/stateexit/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateExitDefaultWidth,
		name/.initial=stateexit-\thetikzumlStateExitNum,
		color/.initial=\tikzumlDefaultDrawColor, style/.style={},
		no coords/.is if=tikzumlstateexitWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/stateexit/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/stateexit/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/stateexit/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlstateexit, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/stateexit/.cd, #1}
	\pgfkeys{/tikzuml/stateexit/.cd, x/.get=\tikzumlStateExitX, y/.get=\tikzumlStateExitY, width/.get=\tikzumlStateExitMinimumWidth,
		name/.get=\tikzumlStateExitName, color/.get=\tikzumlStateExitColor
	}

	\def\tikzumlStateExitPos{\tikzumlStateExitX,\tikzumlStateExitY}

	\iftikzumlstateexitWithoutCoords
		\node[circle, minimum size=\tikzumlStateExitMinimumWidth, draw=\tikzumlStateExitColor, /tikzuml/stateexit/style] (\tikzumlStateExitName) {};
	\else
		\node[circle, minimum size=\tikzumlStateExitMinimumWidth, draw=\tikzumlStateExitColor, /tikzuml/stateexit/style] (\tikzumlStateExitName) at (\tikzumlStateExitPos) {};
	\fi
	\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}
}

% define a uml end state
% args : name of the state
% optional : x,y: coordinates of the state
%            width: width of the state node
%            name: name of the state node
%            color: color of the join symbol
%            style: to manage every default TikZ option
%            no coords: to tell that the state position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlstateend}[1][]{
	\pgfkeys{/tikzuml/stateend/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateEndDefaultWidth,
		name/.initial=stateend-\thetikzumlStateEndNum,
		color/.initial=\tikzumlDefaultDrawColor, style/.style={},
		no coords/.is if=tikzumlstateendWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/stateend/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/stateend/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/stateend/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlstateend, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/stateend/.cd, #1}
	\pgfkeys{/tikzuml/stateend/.cd, x/.get=\tikzumlStateEndX, y/.get=\tikzumlStateEndY, width/.get=\tikzumlStateEndMinimumWidth,
		name/.get=\tikzumlStateEndName, color/.get=\tikzumlStateEndColor
	}

	\def\tikzumlStateEndPos{\tikzumlStateEndX,\tikzumlStateEndY}

	\iftikzumlstateendWithoutCoords
		\node[circle, minimum size=\tikzumlStateEndMinimumWidth, /tikzuml/stateend/style] (\tikzumlStateEndName) {};
	\else
		\node[circle, minimum size=\tikzumlStateEndMinimumWidth, /tikzuml/stateend/style] (\tikzumlStateEndName) at (\tikzumlStateEndPos) {};
	\fi
	\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}
}

% define a uml history state
% args : name of the state
% optional : x,y: coordinates of the state
%            width: width of the state node
%            name: name of the state node
%            color: color of the join symbol
%            style: to manage every default TikZ option
%            no coords: to tell that the state position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlstatehistory}[1][]{
	\pgfkeys{/tikzuml/statehistory/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateHistoryDefaultWidth,
		name/.initial=statehistory-\thetikzumlStateHistoryNum,
		color/.initial=\tikzumlDefaultDrawColor, style/.style={},
		no coords/.is if=tikzumlstatehistoryWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/statehistory/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/statehistory/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/statehistory/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlstatehistory, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/statehistory/.cd, #1}
	\pgfkeys{/tikzuml/statehistory/.cd, x/.get=\tikzumlStateHistoryX, y/.get=\tikzumlStateHistoryY, width/.get=\tikzumlStateHistoryMinimumWidth,
		name/.get=\tikzumlStateHistoryName, color/.get=\tikzumlStateHistoryColor
	}

	\def\tikzumlStateHistoryPos{\tikzumlStateHistoryX,\tikzumlStateHistoryY}

	\iftikzumlstatehistoryWithoutCoords
		\node[circle, minimum size=\tikzumlStateHistoryMinimumWidth, draw=\tikzumlStateHistoryColor, /tikzuml/statehistory/style] (\tikzumlStateHistoryName) {\picturedhistory{draw=\tikzumlStateHistoryColor}};
	\else
		\node[circle, minimum size=\tikzumlStateHistoryMinimumWidth, draw=\tikzumlStateHistoryColor, /tikzuml/statehistory/style] (\tikzumlStateHistoryName) at (\tikzumlStateHistoryPos) {\picturedhistory{draw=\tikzumlStateHistoryColor}};
	\fi

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

% define a uml deep-history state
% args : name of the state
% optional : x,y: coordinates of the state
%            width: width of the state node
%            name: name of the state node
%            color: color of the join symbol
%            style: to manage every default TikZ option
%            no coords: to tell that the state position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\newcommand{\umlstatedeephistory}[1][]{
	\pgfkeys{/tikzuml/statedeephistory/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateDeepHistoryDefaultWidth,
		name/.initial=statedeephistory-\thetikzumlStateDeepHistoryNum,
		color/.initial=\tikzumlDefaultDrawColor, style/.style={},
		no coords/.is if=tikzumlstatedeephistoryWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/statedeephistory/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/statedeephistory/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/statedeephistory/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlstatedeephistory, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/statedeephistory/.cd, #1}
	\pgfkeys{/tikzuml/statedeephistory/.cd, x/.get=\tikzumlStateDeepHistoryX, y/.get=\tikzumlStateDeepHistoryY, width/.get=\tikzumlStateDeepHistoryMinimumWidth,
		name/.get=\tikzumlStateDeepHistoryName, color/.get=\tikzumlStateDeepHistoryColor
	}

	\def\tikzumlStateDeepHistoryPos{\tikzumlStateDeepHistoryX,\tikzumlStateDeepHistoryY}

	\iftikzumlstatedeephistoryWithoutCoords
		\node[circle, minimum size=\tikzumlStateDeepHistoryMinimumWidth, draw=\tikzumlStateDeepHistoryColor, /tikzuml/statedeephistory/style] (\tikzumlStateDeepHistoryName) {\pictureddeephistory{draw=\tikzumlStateDeepHistoryColor}};
	\else
		\node[circle, minimum size=\tikzumlStateDeepHistoryMinimumWidth, draw=\tikzumlStateDeepHistoryColor, /tikzuml/statedeephistory/style] (\tikzumlStateDeepHistoryName) at (\tikzumlStateDeepHistoryPos) {\pictureddeephistory{draw=\tikzumlStateDeepHistoryColor}};
	\fi

	% 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 : x,y: coordinates of the state
%            width: width of the state node
%            name: name of the state node
%            entry, do, exit: entry/do/exit action of the state
%            draw, fill, text: colors
%            style: to manage every default TikZ option
%            no coords: to tell that the state position is defined relatively
%                       to another node (automatically used with TikZ options above, below, left, right, below left, ...)
\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=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateDefaultWidth,
		name/.initial={},
		entry/.initial={}, do/.initial={}, exit/.initial={},
		draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlStateDefaultFillColor,
		text/.initial=\tikzumlDefaultTextColor, style/.style={},
		no coords/.is if=tikzumlstateWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/state/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/state/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/state/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlstate, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/state/.cd, #1}
	\pgfkeys{/tikzuml/state/.cd, x/.get=\tikzumlStateXShift, y/.get=\tikzumlStateYShift, width/.get=\tikzumlStateMinimumWidth, name/.get=\tikzumlStateName,
		entry/.get=\tikzumlStateEntry, do/.get=\tikzumlStateDo, exit/.get=\tikzumlStateExit,
		draw/.get=\tikzumlStateDrawColor, fill/.get=\tikzumlStateFillColor,
		text/.get=\tikzumlStateTextColor
	}

	\ifthenelse{\equal{\tikzumlStateName}{}}{
		\edef\tikzumlState@name{#2}
	}{
		\edef\tikzumlState@name{\tikzumlStateName}
	}

	\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=\tikzumlStateXShift cm, yshift=\tikzumlStateYShift cm]
}{

	\def\tikzumlstaterootlabel{\phantom{\tikzumlState@nodeName}}

	\def\tikzumlstaterootinnerysep{0.5ex}
	\def\tikzumlstatebodyinnerysep{2ex}

	\ifthenelse{\equal{\tikzumlStateEntry}{}}{}{
		\ifnum\c@tikzumlStateText=0
			\def\tikzumlStateText{entry/\tikzumlStateEntry}
		\else
			\let\tikzumlStateTextOld\tikzumlStateText
			\ifthenelse{\equal{\tikzumlStateText}{tikzumlEmpty}}{
				\def\tikzumlStateText{entry/\tikzumlStateEntry}
			}{
				\expandafter\def\expandafter\tikzumlStateText\expandafter{\tikzumlStateTextOld \\ entry/\tikzumlStateEntry}
			}
		\fi
		\setcounter{tikzumlStateText}{1}
		\ifnum\c@tikzumlStateSubStateNum=0
			\def\tikzumlstatebodyinnerysep{0}
			\def\tikzumlstaterootinnerysep{0}
		\fi
	}
	\ifthenelse{\equal{\tikzumlStateDo}{}}{}{
		\ifnum\c@tikzumlStateText=0
			\def\tikzumlStateText{do/\tikzumlStateDo}
		\else
			\let\tikzumlStateTextOld\tikzumlStateText
			\ifthenelse{\equal{\tikzumlStateText}{tikzumlEmpty}}{
				\def\tikzumlStateText{do/\tikzumlStateDo}
			}{
				\expandafter\def\expandafter\tikzumlStateText\expandafter{\tikzumlStateTextOld \\ do/\tikzumlStateDo}
			}
		\fi
		\setcounter{tikzumlStateText}{1}
		\ifnum\c@tikzumlStateSubStateNum=0
			\def\tikzumlstatebodyinnerysep{0}
			\def\tikzumlstaterootinnerysep{0}
		\fi
	}
	\ifthenelse{\equal{\tikzumlStateExit}{}}{}{
		\ifnum\c@tikzumlStateText=0
			\def\tikzumlStateText{exit/\tikzumlStateExit}
		\else
			\let\tikzumlStateTextOld\tikzumlStateText
			\ifthenelse{\equal{\tikzumlStateText}{tikzumlEmpty}}{
				\def\tikzumlStateText{exit/\tikzumlStateExit}
			}{
				\expandafter\def\expandafter\tikzumlStateText\expandafter{\tikzumlStateTextOld \\ exit/\tikzumlStateExit}
			}
		\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
		\iftikzumlstateWithoutCoords
			\node[inner ysep=\tikzumlstaterootinnerysep, minimum width=\tikzumlStateMinimumWidth, /tikzuml/state/style] (\tikzumlState@nodeName-root) {\tikzumlstaterootlabel};
		\else
			\node[inner ysep=\tikzumlstaterootinnerysep, minimum width=\tikzumlStateMinimumWidth, /tikzuml/state/style] (\tikzumlState@nodeName-root) at (0,0) {\tikzumlstaterootlabel};
		\fi
		\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, /tikzuml/state/style ] (\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};
	\ifnum\c@tikzumlStateText=1
		\node[rounded corners, draw=\tikzumlStateDrawColor, fill=\tikzumlStateFillColor, name=\tikzumlState@nodeName, fit=(\tikzumlState@nodeName-body) (\tikzumlState@nodeName-texttmp) (\tikzumlState@nodeName-captiontmp)] {};
	\else
		\node[rounded corners, draw=\tikzumlStateDrawColor, fill=\tikzumlStateFillColor, name=\tikzumlState@nodeName, fit=(\tikzumlState@nodeName-body) (\tikzumlState@nodeName-captiontmp)] {};
	\fi
	\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, to be used inside umlstate environment
\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 and object diagrams                   %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\tikzstyle{tikzuml synchron-msg style}=[color=\tikzumlDefaultDrawColor, -{Triangle[scale=2.5,angle'=50]}]
\tikzstyle{tikzuml asynchron-msg style}=[color=\tikzumlDefaultDrawColor, -{Straight Barb[scale=3.5,angle'=55]}]
\tikzstyle{tikzuml return-msg style}=[color=\tikzumlDefaultDrawColor, dashed, -{Straight Barb[scale=3.5,angle'=55]}]
\tikzstyle{tikzuml call return style}=[color=\tikzumlDefaultDrawColor, dashed, -{Straight Barb[scale=3.5,angle'=55]}]
\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}

\newif\iftikzumlobjectNoDDots
\newif\iftikzumlcreatecallNoDDots

% 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
					\let\keyvalue=\pgfkeyscurrentvalue
					\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
					\let\keyvalue=\pgfkeyscurrentvalue
					\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=\tikzumlDefaultFont]
}{
	% 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[dashed] (\id) -- (end-\id);
	}
	\end{pgfonlayer}
	\end{scope}
}

% define an object diagram

\newenvironment{umlobjdiag}{
	\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
					\let\keyvalue=\pgfkeyscurrentvalue
					\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
					\let\keyvalue=\pgfkeyscurrentvalue
					\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=\tikzumlDefaultFont]
}{
	% 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 database 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 entity 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 boundary 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 control 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
%            stereo: stereotype of the object (object, actor, database, boundary, control, entity, multiobject)
%            class: class of the object
%            scale: scale factor of the object symbol
%            draw, fill, text; colors
%            no ddots: when used, disable printing of double dots
\newcommand{\umlobject}[2][]{
	\stepcounter{tikzumlObjectNum}

	\edef\tikzumlobject@ddot{:}
	\edef\tikzumlobject@kern{\,}
	\pgfkeys{/tikzuml/obj/.cd, x/.initial=tikzumlEmpty, y/.initial=\tikzumlDefaultX, stereo/.initial=\tikzumlObjectDefaultStereo,
		class/.initial={}, scale/.initial=1,
		draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlObjectDefaultFillColor,
		text/.initial=\tikzumlDefaultTextColor,
		no ddots/.is if=tikzumlobjectNoDDots,
		no ddots=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\errmessage{TIKZUML ERROR : in umlobject, 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=\tikzumlObjectDrawColor, fill/.get=\tikzumlObjectFillColor,
		text/.get=\tikzumlObjectTextColor
	}

	\iftikzumlobjectNoDDots
		\edef\tikzumlobject@ddot{}
		\edef\tikzumlobject@kern{}
	\fi

	\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
		\expandafter\xdef\expandafter\tikzumlIdList\expandafter{\tikzumlIdListOld,\tikzumlObjectName}
	\fi

	\tikzstyle{tikzuml object box style}=[rectangle, text=\tikzumlObjectTextColor, font=\tikzumlDefaultFont]

	\ifthenelse{\equal{\tikzumlObjectStereo}{object}}{
		\tikzstyle{tikzuml object box style}+=[draw=\tikzumlObjectDrawColor, fill=\tikzumlObjectFillColor]
	}{
		\ifthenelse{\equal{\tikzumlObjectStereo}{multi}}{
			\tikzstyle{tikzuml object box style}+=[fill=\tikzumlObjectFillColor]
		}{}
	}

	\ifdefempty{\tikzumlObjectName}{
		\def\tikzumlObjectNC{@COLON@\tikzumlObjectClass}
	}{
		\def\tikzumlObjectNC{\tikzumlObjectName}
	}
	\ifnum\tikzumlInCreateCall=1
		\draw (\tikzumlCreateCallObjectSrc -| \tikzumlObjectX,0) node[tikzuml object box style] (\tikzumlObjectNC) {\underline{\textbf{\tikzumlObjectName\tikzumlobject@kern\tikzumlobject@ddot\tikzumlobject@kern\tikzumlObjectClass}}};
	\else
		\node[tikzuml object box style] (\tikzumlObjectNC) at (\tikzumlObjectX,\tikzumlObjectY) {\underline{\textbf{\tikzumlObjectName\tikzumlobject@kern\tikzumlobject@ddot\tikzumlobject@kern\tikzumlObjectClass}}};
	\fi

	\ifthenelse{\equal{\tikzumlObjectStereo}{multi}}{
		\draw (\tikzumlObjectNC.north east)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-tr, coordinate] {};
		\draw (\tikzumlObjectNC.north west)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-tl, coordinate] {};
		\draw (\tikzumlObjectNC.south east)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-br, coordinate] {};
		\draw (\tikzumlObjectNC-tr)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-ttr, coordinate] {};
		\draw (\tikzumlObjectNC-tl)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-ttl, coordinate] {};
		\draw (\tikzumlObjectNC-br)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-tbr, coordinate] {};
		\fill[fill=\tikzumlObjectFillColor] (\tikzumlObjectNC-ttl |- \tikzumlObjectNC.north) -- (\tikzumlObjectNC-ttl) -- (\tikzumlObjectNC-ttr) -- (\tikzumlObjectNC-tbr) -- (\tikzumlObjectNC-tbr -| \tikzumlObjectNC.east) -- (\tikzumlObjectNC.north east) -- (\tikzumlObjectNC-ttl |- \tikzumlObjectNC.north);
		\draw[draw=\tikzumlObjectDrawColor] (\tikzumlObjectNC-ttl |- \tikzumlObjectNC.north) -- (\tikzumlObjectNC-ttl) -- (\tikzumlObjectNC-ttr) -- (\tikzumlObjectNC-tbr) -- (\tikzumlObjectNC-tbr -| \tikzumlObjectNC.east);
		\fill[fill=\tikzumlObjectFillColor] (\tikzumlObjectNC-tl |- \tikzumlObjectNC.north) -- (\tikzumlObjectNC-tl) -- (\tikzumlObjectNC-tr) -- (\tikzumlObjectNC-br) -- (\tikzumlObjectNC-br -| \tikzumlObjectNC.east) -- (\tikzumlObjectNC.north east) -- (\tikzumlObjectNC-tl |- \tikzumlObjectNC.north);
		\draw[draw=\tikzumlObjectDrawColor] (\tikzumlObjectNC-tl |- \tikzumlObjectNC.north) -- (\tikzumlObjectNC-tl) -- (\tikzumlObjectNC-tr) -- (\tikzumlObjectNC-br) -- (\tikzumlObjectNC-br -| \tikzumlObjectNC.east);
		\draw[draw=\tikzumlObjectDrawColor] (\tikzumlObjectNC.north west) rectangle (\tikzumlObjectNC.south east);
	}{
		\ifthenelse{\equal{\tikzumlObjectStereo}{object}}{}{
			\node[above=1ex, name=\tikzumlObjectNC-picture] at (\tikzumlObjectNC) {\csname pictured\tikzumlObjectStereo \endcsname{draw=\tikzumlObjectDrawColor, fill=\tikzumlObjectFillColor, scale=\tikzumlObjectScale}};
		}
	}
}

% shortcuts for objects
\newcommand{\umlbasicobject}[2][]{
	\pgfkeys{/tikzuml/basicobj/.cd, .unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\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
			\let\keyvalue=\pgfkeyscurrentvalue
			\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
			\let\keyvalue=\pgfkeyscurrentvalue
			\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
			\let\keyvalue=\pgfkeyscurrentvalue
			\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
			\let\keyvalue=\pgfkeyscurrentvalue
			\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
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{stereo}}{
				\errmessage{TIKZUML ERROR : in umlmulti, forbidden option stereo}
			}{}
		}
	}
	\pgfkeys{/tikzuml/multiobj/.cd, #1}
	\umlobject[stereo=multi, #1]{#2}
}

\newcounter{tikzumlSDNodeNum}

% define a hidden node to lengthen lifeline of a object
% args : object node
% optional : dt: distance between the sdnode and the last call defined on the lifeline of the object
%            name: name of the sdnode
\newcommand{\umlsdnode}[2][]{
	\pgfkeys{/tikzuml/sdnode/.cd, dt/.initial=0, name/.initial=tikzumlEmpty}
	\pgfkeys{/tikzuml/sdnode/.cd, #1}
	\pgfkeys{/tikzuml/sdnode/.cd, dt/.get=\tikzumlSDNodeDT, name/.get=\tikzumlSDNodeName}

	\ifthenelse{\equal{\tikzumlSDNodeName}{tikzumlEmpty}}{
		\expandafter\def\expandafter\tikzumlSDNode@nodeName{sdnode-\thetikzumlSDNodeNum}
	}{
		\expandafter\def\expandafter\tikzumlSDNode@nodeName{\tikzumlSDNodeName}
	}

	\stepcounter{tikzumlSDNodeNum}

	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlSDNode@objnodeName{#2}}\x

	\draw (\expandafter\csname tikzumlLastChild@\tikzumlSDNode@objnodeName \endcsname)+(0,-\tikzumlSDNodeDT ex) node[name=\tikzumlSDNode@nodeName,coordinate] {};

	% update last node drawn on sender lifeline
	\expandafter\xdef\csname tikzumlLastChild@\tikzumlSDNode@objnodeName \endcsname{\tikzumlSDNode@nodeName}
}

\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: name of the call
%            op: operation name and input args
%            return: return value
%            type: type of the call (synchron, asynchron)
%            draw, fill, text: colors
%            padding: 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=\tikzumlCallDefaultDT, name/.initial={call-\thetikzumlCallNum},
		op/.initial={}, return/.initial={}, type/.initial=\tikzumlCallDefaultType,
		draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlCallDefaultFillColor,
		text/.initial=\tikzumlDefaultTextColor,
		padding/.initial=\tikzumlCallDefaultPadding,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\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=\tikzumlCallDrawColor, fill/.get=\tikzumlCallFillColor,
		text/.get=\tikzumlCallTextColor
	}

	\edef\tikzumlfillcall{\tikzumlCallFillColor}
	\edef\tikzumldrawcall{\tikzumlCallDrawColor}
	\edef\tikzumltextcall{\tikzumlCallTextColor}
	\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
	\ifstrequal{\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
		\ifstrequal{\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) {};
		}{
			\ifstrequal{\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{\tikzumlCallDefaultFillColor}{\tikzumlCallFillColor}}{}{
		\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,-\tikzumlCallPadding ex)
			node[font=\tikzumlDefaultFont, text=\tikzumltextcall, midway, right, name=\tikzumlCall@nodeName-op] {\tikzumlCallOp}
			-- ++(-2.5*\tikzumlCallPadding ex,0);

		% 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=\tikzumlDefaultFont, 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=\tikzumlDefaultFont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-op] {\tikzumlCallOp};
		}{
			\draw[\tikzumlcallstyle, \tikzumldrawcall] (st-\tikzumlCall@nodeName.west) -- (et-\tikzumlCall@nodeName.east)
				node[font=\tikzumlDefaultFont, 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=\tikzumlDefaultFont, 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=\tikzumlDefaultFont, 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: name of fragment
%            type: type of fragment (opt, alt, break, loop, par, critical, ignore, consider, assert, neg, weak, strict, ref)
%            label: label of fragment (ex : condition for opt, iterator for loop, ...)
%            inner xsep, inner 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=\tikzumlFragmentDefaultType,
		label/.initial=tikzumlEmpty,
		inner xsep/.initial=\tikzumlFragmentDefaultXSep, inner ysep/.initial=\tikzumlFragmentDefaultYSep,
		draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlFragmentDefaultFillColor,
		text/.initial=\tikzumlDefaultTextColor,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\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=\tikzumlFragmentDrawColor, fill/.get=\tikzumlFragmentFillColor,
		text/.get=\tikzumlFragmentTextColor
	}

	\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=\tikzumlFragmentTextColor, font=\tikzumlDefaultFont, anchor=north east, name=\tikzumlFragment@name-type]
		at (\tikzumlFragment@name-back.north west) {\tikzumlFragmentType};
	\node[text=\tikzumlFragmentTextColor, font=\tikzumlDefaultFont, anchor=north west, name=\tikzumlFragment@name-label]
		at (\tikzumlFragment@name-type.south west) {\tikzumlFragmentLabel};

	% draw final fragment box
	\begin{pgfonlayer}{fragment\thetikzumlFragmentLevel}
	\node[draw=\tikzumlFragmentDrawColor, fill=\tikzumlFragmentFillColor, outer sep=0, inner sep=0, font=\tikzumlDefaultFont, fit=(\tikzumlFragment@name-back) (\tikzumlFragment@name-type) (\tikzumlFragment@name-label), name=\tikzumlFragment@name] {};
	\end{pgfonlayer}

	\draw[draw=\tikzumlFragmentDrawColor] (\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
%            stereo: stereotype of the new object
%            class: class type of the new object
%            dt: time delay from last event
%            name: name of the call
%            draw, fill, text: colors
%            no ddots: when used, disable printing of double dots
\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=\tikzumlObjectDefaultStereo, class/.initial={},
		dt/.initial=\tikzumlCreateCallDefaultDT, name/.initial=call-\thetikzumlCallNum,
		draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlCallDefaultFillColor,
		text/.initial=\tikzumlDefaultTextColor,
		draw obj/.initial=\tikzumlDefaultDrawColor, fill obj/.initial=\tikzumlObjectDefaultFillColor,
		text obj/.initial=\tikzumlDefaultTextColor,
		no ddots/.is if=tikzumlcreatecallNoDDots,
		no ddots=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\errmessage{TIKZUML ERROR : in umlcreatecall, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/createcall/.cd, #1}
	\pgfkeys{/tikzuml/createcall/.cd, x/.get=\tikzumlCreateCallX, stereo/.get=\tikzumlCreateCallStereo,
		class/.get=\tikzumlCreateCallClass,
		dt/.get=\tikzumlCreateCallDT, name/.get=\tikzumlCreateCallName,
		draw/.get=\tikzumlCreateCallDrawColor, fill/.get=\tikzumlCreateCallFillColor,
		text/.get=\tikzumlCreateCallTextColor,
		draw obj/.get=\tikzumlCreateCallObjectDrawColor, fill obj/.get=\tikzumlCreateCallObjectFillColor,
		text obj/.get=\tikzumlCreateCallObjectTextColor
	}

	\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\tikzumlCreateCallDTold\tikzumlCreateCallDT
		\pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCreateCallDTold}
		\edef\tikzumlCreateCallDT{\pgfmathresult}
		\addtocounter{tikzumlCallStartFragmentNum}{-1}
	\fi
	\ifnum\thetikzumlCallEndFragmentNum>0
		\let\tikzumlCreateCallDTold\tikzumlCreateCallDT
		\pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCreateCallDTold}
		\edef\tikzumlCreateCallDT{\pgfmathresult}
		\addtocounter{tikzumlCallEndFragmentNum}{-1}
	\fi
	\ifnum\thetikzumlFragmentPartNum>0
		\let\tikzumlCreateCallDTold\tikzumlCreateCallDT
		\pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCreateCallDTold}
		\edef\tikzumlCreateCallDT{\pgfmathresult}
	\fi

	% managing parent-child structure
	\ifnum\thetikzumlCallLevel>0
		\let\tikzumlCall@nameold\tikzumlCall@name
		\def\tikzumlCall@name{\tikzumlCreateCallName}
		\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{\tikzumlCreateCallName}
	\fi

	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlCreateCall@nodeName{\tikzumlCall@name}}\x

	\draw (\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname)+(0,-\tikzumlCreateCallDT ex) node[name=st-\tikzumlCreateCall@nodeName, tikzuml activity style] {};

	\xdef\tikzumlCreateCallObjectSrc{st-\tikzumlCreateCall@nodeName}

	\iftikzumlcreatecallNoDDots
		\umlobject[x=\tikzumlCreateCallX, stereo=\tikzumlCreateCallStereo, class=\tikzumlCreateCallClass, draw=\tikzumlCreateCallObjectDrawColor, fill=\tikzumlCreateCallObjectFillColor, text=\tikzumlCreateCallObjectTextColor, no ddots]{#3}
	\else
		\umlobject[x=\tikzumlCreateCallX, stereo=\tikzumlCreateCallStereo, class=\tikzumlCreateCallClass, draw=\tikzumlCreateCallObjectDrawColor, fill=\tikzumlCreateCallObjectFillColor, text=\tikzumlCreateCallObjectTextColor]{#3}
	\fi

	\draw (\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname |- #3)+(0,-0.5*\tikzumlCreateCallDT 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, \tikzumlCreateCallDrawColor] (st-\tikzumlCreateCall@nodeName) -- (#3) node[midway, above, font=\tikzumlDefaultFont, text=\tikzumlCreateCallTextColor, name=\tikzumlCreateCall@nodeName-op] {create};
	\end{pgfonlayer}

	\ifnum\thetikzumlCallLevel=0
		\begin{pgfonlayer}{activity}
		\draw[draw=\tikzumlCreateCallDrawColor, fill=\tikzumlCreateCallFillColor] (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=\tikzumlDefaultDrawColor, -]

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

\newif\iftikzumlcomponentWithoutCoords

\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=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlComponentDefaultWidth, name/.initial={},
		draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlComponentDefaultFillColor,
		text/.initial=\tikzumlDefaultTextColor, style/.style={},
		no coords/.is if=tikzumlcomponentWithoutCoords,
		no coords=false,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{above}\OR
				\equal{\keyname}{left}\OR
				\equal{\keyname}{below}\OR
				\equal{\keyname}{right}\OR
				\equal{\keyname}{above left}\OR
				\equal{\keyname}{above right}\OR
				\equal{\keyname}{below left}\OR
				\equal{\keyname}{below right}
			}{
				\IfSubStr{\keyvalue}{ of }{
					\pgfkeys{/tikzuml/component/.cd, no coords}
				}{}
			}{}
			\ifx\keyvalue\pgfkeysnovalue
				\pgfkeys{/tikzuml/component/.cd, style/.append style/.expand once={\keyname}}
			\else
				\pgfkeys{/tikzuml/component/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}
			\fi
			%\errmessage{TIKZUML ERROR : in umlcomponent, invalid option \keyname}
		}
	}
	\pgfkeys{/tikzuml/component/.cd, #1}
	\pgfkeys{/tikzuml/component/.cd, x/.get=\tikzumlComponentXShift, y/.get=\tikzumlComponentYShift,
		width/.get=\tikzumlComponentMinimumWidth, name/.get=\tikzumlComponentName,
		draw/.get=\tikzumlComponentDrawColor, fill/.get=\tikzumlComponentFillColor,
		text/.get=\tikzumlComponentTextColor
	}

	\ifthenelse{\equal{\tikzumlComponentName}{}}{
		\edef\tikzumlComponent@name{#2}
	}{
		\edef\tikzumlComponent@name{\tikzumlComponentName}
	}

	\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=\tikzumlComponentXShift cm, yshift=\tikzumlComponentYShift 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
		\iftikzumlcomponentWithoutCoords
			\node[inner ysep=0.5ex, minimum width=\tikzumlComponentMinimumWidth, font=\tikzumlDefaultFont, /tikzuml/component/style] (\tikzumlComponent@nodeName-root)  {\phantom{\tikzumlComponent@nodeName}};
		\else
			\node[inner ysep=0.5ex, minimum width=\tikzumlComponentMinimumWidth, font=\tikzumlDefaultFont, /tikzuml/component/style] (\tikzumlComponent@nodeName-root) at (0,0) {\phantom{\tikzumlComponent@nodeName}};
		\fi
		\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=\tikzumlDefaultFont, fit = \csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname] (\tikzumlComponent@nodeName-body) {};
	\node[above, font=\tikzumlDefaultFont] (\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=\tikzumlComponentDrawColor, fill=\tikzumlComponentFillColor, font=\tikzumlDefaultFont} };
	\node[draw=\tikzumlComponentDrawColor, fill=\tikzumlComponentFillColor, name=\tikzumlComponent@nodeName, /tikzuml/component/style, fit=(\tikzumlComponent@nodeName-body) (\tikzumlComponent@nodeName-captiontmp)] {};
	\node[font=\tikzumlDefaultFont] (\tikzumlComponent@nodeName-caption) at (\tikzumlComponent@nodeName-captiontmp) {\tikzumlComponent@caption};
	\draw (\tikzumlComponent@nodeName-caption.north -| \tikzumlComponent@nodeName.east) node[font=\tikzumlDefaultFont, xshift=-1ex, below=-1ex, name=\tikzumlComponent@nodeName-logo] {\picturedcomponent{draw=\tikzumlComponentDrawColor, fill=\tikzumlComponentFillColor, font=\tikzumlDefaultFont} };
	\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 component
\newcommand{\umlbasiccomponent}[2][]{\begin{umlcomponent}[#1]{#2} \end{umlcomponent}}

\newcommand{\umlrequiredinterface}[2][]{
	\def\tikzumlInterfaceWithPort{tikzumlFalse}
	\pgfkeys{/tikzuml/requiredinterfacerelation/.cd, interface/.initial={}, distance/.initial=\tikzumlRequiredInterfaceDefaultDistance,
		name/.initial=tikzumlEmpty, width/.initial=\tikzumlRequiredInterfaceDefaultWidth,
		padding/.initial=\tikzumlRequiredInterfaceDefaultPadding,
		draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlComponentDefaultFillColor,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{with port}}{
				\def\tikzumlInterfaceWithPort{tikzumlTrue}
			}{}
		}
	}
	\pgfkeys{/tikzuml/requiredinterfacerelation/.cd, #1}
	\pgfkeys{/tikzuml/requiredinterfacerelation/.cd, interface/.get=\tikzumlRequiredInterfaceLabel,
		distance/.get=\tikzumlRequiredInterfaceDistance,
		name/.get=\tikzumlRequiredInterfaceName,
		width/.get=\tikzumlRequiredInterfaceWidth,
		padding/.get=\tikzumlRequiredInterfacePadding,
		draw/.get=\tikzumlRequiredInterfaceDrawColor,
		fill/.get=\tikzumlRequiredInterfaceFillColor
	}

	\ifthenelse{\equal{\tikzumlRequiredInterfaceName}{tikzumlEmpty}}{
		\edef\tikzumlRequiredInterface@interfacename{#2-east-interface}
		\edef\tikzumlRequiredInterface@portname{#2-east-port}
		\edef\tikzumlRequiredInterface@paddingname{#2-east-padding}
	}{
		\edef\tikzumlRequiredInterface@interfacename{\tikzumlRequiredInterfaceName}
		\edef\tikzumlRequiredInterface@portname{\tikzumlRequiredInterfaceName-port}
		\edef\tikzumlRequiredInterface@paddingname{\tikzumlRequiredInterfaceName-padding}
	}

	\edef\tikzumlRequiredInterface@name{#2}

	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlRequiredInterface@nodeName{\tikzumlRequiredInterface@name}}\x

	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlRequiredInterface@interfacenodeName{\tikzumlRequiredInterface@interfacename}}\x

	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlRequiredInterface@portnodeName{\tikzumlRequiredInterface@portname}}\x

	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlRequiredInterface@paddingnodeName{\tikzumlRequiredInterface@paddingname}}\x

	\ifthenelse{\equal{\tikzumlInterfaceWithPort}{tikzumlTrue}}{
		\node[inner sep=0.5*\tikzumlRequiredInterfaceWidth, rectangle, draw=\tikzumlRequiredInterfaceDrawColor, fill=\tikzumlRequiredInterfaceFillColor] (\tikzumlRequiredInterface@portnodeName) 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@interfacenodeName-tmp] {};
	\clip (\tikzumlRequiredInterface@interfacenodeName-tmp.north) rectangle (\tikzumlRequiredInterface@interfacenodeName-tmp.south -| \tikzumlRequiredInterface@interfacenodeName-tmp.west);
	\node[inner sep=0, text width=\tikzumlRequiredInterfaceWidth, circle, draw=\tikzumlRequiredInterfaceDrawColor] (\tikzumlRequiredInterface@interfacenodeName) at (\tikzumlRequiredInterface@interfacenodeName-tmp) {};
	\end{scope}
	\node[above] at (\tikzumlRequiredInterface@interfacenodeName.north) {\tikzumlRequiredInterfaceLabel};

	\umlrelation[style={tikzuml connector style}, #1]{\tikzumlRequiredInterface@portnodeName}{\tikzumlRequiredInterface@interfacenodeName}

	\draw (\tikzumlRequiredInterface@interfacenodeName)+(\tikzumlRequiredInterfacePadding,0) node[name=\tikzumlRequiredInterface@paddingnodeName] {};

	% 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@paddingnodeName) (\tikzumlRequiredInterface@portnodeName) }
	\fi
}

\newcommand{\umlprovidedinterface}[2][]{
	\def\tikzumlInterfaceWithPort{tikzumlFalse}
	\pgfkeys{/tikzuml/providedinterfacerelation/.cd, interface/.initial={}, distance/.initial=\tikzumlProvidedInterfaceDefaultDistance,
		name/.initial=tikzumlEmpty, width/.initial=\tikzumlProvidedInterfaceDefaultWidth,
		padding/.initial=\tikzumlProvidedInterfaceDefaultPadding,
		draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlComponentDefaultFillColor,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\ifthenelse{\equal{\keyname}{with port}}{
				\def\tikzumlInterfaceWithPort{tikzumlTrue}
			}{}
		}
	}
	\pgfkeys{/tikzuml/providedinterfacerelation/.cd, #1}
	\pgfkeys{/tikzuml/providedinterfacerelation/.cd, interface/.get=\tikzumlProvidedInterfaceLabel,
		distance/.get=\tikzumlProvidedInterfaceDistance,
		name/.get=\tikzumlProvidedInterfaceName,
		width/.get=\tikzumlProvidedInterfaceWidth,
		padding/.get=\tikzumlProvidedInterfacePadding,
		draw/.get=\tikzumlProvidedInterfaceDrawColor,
		fill/.get=\tikzumlProvidedInterfaceFillColor
	}

	\ifthenelse{\equal{\tikzumlProvidedInterfaceName}{tikzumlEmpty}}{
		\edef\tikzumlProvidedInterface@interfacename{#2-west-interface}
		\edef\tikzumlProvidedInterface@portname{#2-west-port}
		\edef\tikzumlProvidedInterface@paddingname{#2-west-padding}
	}{
		\edef\tikzumlProvidedInterface@interfacename{\tikzumlProvidedInterfaceName}
		\edef\tikzumlProvidedInterface@portname{\tikzumlProvidedInterfaceName-port}
		\edef\tikzumlProvidedInterface@paddingname{\tikzumlProvidedInterfaceName-padding}
	}

	\edef\tikzumlProvidedInterface@name{#2}

	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlProvidedInterface@nodeName{\tikzumlProvidedInterface@name}}\x

	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlProvidedInterface@interfacenodeName{\tikzumlProvidedInterface@interfacename}}\x

	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlProvidedInterface@portnodeName{\tikzumlProvidedInterface@portname}}\x

	\begingroup
		\def\_{_}\edef\x{\endgroup
			\def\noexpand\tikzumlProvidedInterface@paddingnodeName{\tikzumlProvidedInterface@paddingname}}\x

	\ifthenelse{\equal{\tikzumlInterfaceWithPort}{tikzumlTrue}}{
		\node[inner sep=0.5*\tikzumlProvidedInterfaceWidth, rectangle, draw=\tikzumlProvidedInterfaceDrawColor, fill=\tikzumlProvidedInterfaceFillColor] (\tikzumlProvidedInterface@portnodeName) at (\tikzumlProvidedInterface@nodeName.west) {};
	}{
		\node[inner sep=0] (\tikzumlProvidedInterface@portnodeName) at (\tikzumlProvidedInterface@nodeName.west) {};
	}
	\draw (\tikzumlProvidedInterface@nodeName)+(-\tikzumlProvidedInterfaceDistance,0) node[inner sep=0, text width=\tikzumlProvidedInterfaceWidth, circle, draw=\tikzumlProvidedInterfaceDrawColor, fill=\tikzumlProvidedInterfaceFillColor, name=\tikzumlProvidedInterface@interfacenodeName] {};
	\node[above] at (\tikzumlProvidedInterface@interfacenodeName.north)
 {\tikzumlProvidedInterfaceLabel};

	\umlrelation[style={tikzuml connector style}, #1]{\tikzumlProvidedInterface@portnodeName}{\tikzumlProvidedInterface@interfacenodeName}

	\draw (\tikzumlProvidedInterface@interfacenodeName)+(-\tikzumlProvidedInterfacePadding,0) node[name=\tikzumlProvidedInterface@paddingnodeName] {};

	% 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@paddingnodeName) (\tikzumlProvidedInterface@portnodeName) }
			\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}
\newlength{\tikzuml@AC@labelXShift}
\newlength{\tikzuml@AC@labelYShift}

\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=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorFillColor] (\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=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorFillColor] (\tikzuml@ACInterface@nodeName-ic) at (\tikzuml@AC@xic,\tikzuml@AC@yic) {};
	\end{scope}
	\pgfmathsetlength{\tikzuml@AC@labelXShift}{0pt}
	\pgfmathsetlength{\tikzuml@AC@labelYShift}{0pt}
	\ifthenelse{\equal{\tikzumlAssemblyConnectorLabelPosition}{right}}{
		\pgfmathsetlength{\tikzuml@AC@labelXShift}{0.5*\tikzuml@AC@width}
	}{
		\ifthenelse{\equal{\tikzumlAssemblyConnectorLabelPosition}{left}}{
			\pgfmathsetlength{\tikzuml@AC@labelXShift}{-0.5*\tikzuml@AC@width}
		}{
			\ifthenelse{\equal{\tikzumlAssemblyConnectorLabelPosition}{above}}{
				\pgfmathsetlength{\tikzuml@AC@labelYShift}{0.5*\tikzuml@AC@width}
			}{
				\ifthenelse{\equal{\tikzumlAssemblyConnectorLabelPosition}{below}}{
					\pgfmathsetlength{\tikzuml@AC@labelYShift}{-0.5*\tikzuml@AC@width}
				}{}
			}
		}
	}
	\node[\tikzumlAssemblyConnectorLabelPosition, font=\tikzumlDefaultFont,
		xshift=\tikzuml@AC@labelXShift,
		yshift=\tikzuml@AC@labelYShift] at (\tikzuml@ACInterface@nodeName-interface.center)
 {\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={},
		labelpos/.initial=above,
		arm1/.initial={auto}, arm2/.initial={auto},
		name/.initial=connector-\thetikzumlConnectorNum, width/.initial=1em,
		anchor1/.initial={}, anchor2/.initial={},
		draw/.initial=\tikzumlDefaultDrawColor,
		fill assembly connector/.initial=\tikzumlAssemblyConnectorDefaultFillColor,
		fill port/.initial=\tikzumlPortDefaultFillColor,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\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,
		labelpos/.get=\tikzumlAssemblyConnectorLabelPosition,
		width/.get=\tikzumlAssemblyConnectorWidth,
		arm1/.get=\tikzumlAssemblyConnectorStartArm,
		arm2/.get=\tikzumlAssemblyConnectorEndArm,
		anchor1/.get=\tikzumlAssemblyConnectorStartAnchorTmp,
		anchor2/.get=\tikzumlAssemblyConnectorEndAnchorTmp,
		draw/.get=\tikzumlAssemblyConnectorDrawColor,
		fill assembly connector/.get=\tikzumlAssemblyConnectorFillColor,
		fill port/.get=\tikzumlAssemblyConnectorPortFillColor
	}

	\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{\tikzumlAssemblyConnectorStartAnchorTmp}{}}{
	}{
		\def\tikzumlAssemblyConnectorStartAnchor{\tikzumlAssemblyConnectorStartAnchorTmp}
	}
	\ifthenelse{\equal{\tikzumlAssemblyConnectorEndAnchorTmp}{}}{
	}{
		\def\tikzumlAssemblyConnectorEndAnchor{\tikzumlAssemblyConnectorEndAnchorTmp}
	}

	\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=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorPortFillColor] (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) {};
		\node[inner sep=0.5*\tikzumlAssemblyConnectorWidth, rectangle, draw=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorPortFillColor] (\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlPortDefaultFillColor,
		width/.initial=\tikzumlPortDefaultWidth,
		.unknown/.code={
			\let\keyname=\pgfkeyscurrentname
			\let\keyvalue=\pgfkeyscurrentvalue
			\errmessage{TIKZUML ERROR : in umlport forbidden option \keyname}
		}
	}
	\pgfkeys{/tikzuml/port/.cd, #1}
	\pgfkeys{/tikzuml/port/.cd, width/.get=\tikzumlPortWidth,
		draw/.get=\tikzumlPortDrawColor, fill/.get=\tikzumlPortFillColor}
	\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=\tikzumlPortDrawColor, fill=\tikzumlPortFillColor] (\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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
		\let\keyvalue=\pgfkeyscurrentvalue
		\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-umld.sty
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
