% Specification Description for Unified Process Methodology
%
% Copyright (c) 2006-2007 Stephane GALLAND <galland@arakhne.org>
% 
% This program is free library; you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as
% published by the Free Software Foundation; either version 3 of the
% License, or any later version.
%
% This library is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
% Lesser General Public License for more details.
%
% You should have received a copy of the GNU Lesser General Public
% License along with this library; see the file COPYING.  If not,
% write to the Free Software Foundation, Inc., 59 Temple Place - Suite
% 330, Boston, MA 02111-1307, USA.
%
% Creation date: 2006-04-27
% Modifications:
%   2009-10-30   Clean code.
%   2007-03-19   Add localization.
%

\global\edef\upm@package@spec@ver{2009/10/30}

\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesPackage{upmethodology-spec}[\upm@package@spec@ver]

\RequirePackage{upmethodology-p-common}

\RequirePackage[normalem]{ulem}

\RequirePackage{upmethodology-fmt}
\RequirePackage{upmethodology-code}

%------------------------------------
% LOCALIZATION
%------------------------------------
\def\upm@spec@lang@english {
  \gdef\upm@lang@@{\message{**** upmethodology-spec is using English language ****}}%
  \gdef\upm@spec@lang@description{Description}
  \gdef\upm@spec@lang@returned@values{returned value(s)}
  \gdef\upm@spec@lang@except@for{Except for}
  \gdef\upm@spec@lang@modifier@public{{\tiny+}}
  \gdef\upm@spec@lang@modifier@protected{{\tiny\#}}
  \gdef\upm@spec@lang@modifier@private{{\tiny--}}
  \gdef\upm@spec@lang@modifier@static##1{{\uline{##1}}}
  \gdef\upm@spec@lang@modifier@const{query}
  \gdef\upm@spec@lang@modifier@final{isLeaf}
  \gdef\upm@spec@lang@modifier@abstract{abstract}
  \gdef\upm@spec@lang@modifier@root{isRoot}
  \gdef\upm@spec@lang@modifier@inout{\ensuremath{\leftrightarrow}}
  \gdef\upm@spec@lang@modifier@in{\ensuremath{\rightarrow}}
  \gdef\upm@spec@lang@modifier@out{\ensuremath{\leftarrow}}
}
\def\upm@spec@lang@french {
  \gdef\upm@lang@@{\message{**** upmethodology-spec is using French language ****}}%
  \gdef\upm@spec@lang@description{Description}
  \gdef\upm@spec@lang@returned@values{valeur(s) retourn\'ee(s)}
  \gdef\upm@spec@lang@except@for{Except\'e pour}
  \gdef\upm@spec@lang@modifier@public{{\tiny+}}
  \gdef\upm@spec@lang@modifier@protected{{\tiny\#}}
  \gdef\upm@spec@lang@modifier@private{{\tiny--}}
  \gdef\upm@spec@lang@modifier@static##1{{\uline{##1}}}
  \gdef\upm@spec@lang@modifier@const{requ\^ete}
  \gdef\upm@spec@lang@modifier@final{estFeuille}
  \gdef\upm@spec@lang@modifier@abstract{abstra\^{\i}t}
  \gdef\upm@spec@lang@modifier@root{estRacine}
  \gdef\upm@spec@lang@modifier@inout{\ensuremath{\leftrightarrow}}
  \gdef\upm@spec@lang@modifier@in{\ensuremath{\rightarrow}}
  \gdef\upm@spec@lang@modifier@out{\ensuremath{\leftarrow}}
}

%----------------------------------------
% OPTIONS
%----------------------------------------
\DeclareOption{french}{%
  \upm@spec@lang@french
}
\DeclareOption{francais}{%
  \upm@spec@lang@french
}
\DeclareOption{english}{%
  \upm@spec@lang@english
}
\ExecuteOptions{english}
\ProcessOptions
\upm@lang@@

%------------------------------------
% DETAILLED SPECIFICATION
%------------------------------------

\newlength{\upm@spec@detailspec@description@width}
\setlength{\upm@spec@detailspec@description@width}{3cm}

\newsavebox{\upm@spec@detailspec@savebox}
\newlength{\upm@spec@detailspec@itrn@width}

\newcounter{upm@detailspec@return@counter}
\newcounter{upm@detailspec@function@counter}

\newif\ifupm@spec@showdescription
\newif\ifupm@spec@showparams
\newif\ifupm@spec@showreturns
\newif\ifupm@spec@firstparam
\newif\ifupm@spec@modifier@has@static
\newif\ifupm@spec@modifier@has@const
\newif\ifupm@spec@modifier@has@final
\newif\ifupm@spec@modifier@has@abstract
\newif\ifupm@spec@modifier@has@root
\newif\ifupm@spec@modifier@has@public
\newif\ifupm@spec@modifier@has@protected
\newif\ifupm@spec@modifier@has@private
\newif\ifupm@spec@tmp@a

\newcommand{\upm@spec@head}[2]{#1}
\newcommand{\upm@spec@tail}[2]{#2}

%-----
%\upm@spec@func@modifiers{modifiers}
\newcommand{\upm@spec@func@modifiers}[1]{%
	\global\upm@spec@modifier@has@staticfalse%
	\global\upm@spec@modifier@has@constfalse%
	\global\upm@spec@modifier@has@finalfalse%
	\global\upm@spec@modifier@has@abstractfalse%
	\global\upm@spec@modifier@has@rootfalse%
	\global\upm@spec@modifier@has@publicfalse%
	\global\upm@spec@modifier@has@protectedfalse%
	\global\upm@spec@modifier@has@privatefalse%
	\upm@spec@func@modifiers@scan{#1}%
}
\newcommand{\upm@spec@func@modifiers@scan}[1]{%
	\upm@ifnotempty{#1}{%
		\edef\upm@reserved@a{\upm@spec@head #1\@empty\@empty}%
		\edef\upm@reserved@b{\upm@spec@tail #1\@empty\@empty}%
		\ifthenelse{\equal{\upm@reserved@a}{+}}{%
			%public
			\global\upm@spec@modifier@has@publictrue%
			\global\upm@spec@modifier@has@protectedfalse%
			\global\upm@spec@modifier@has@privatefalse%
		}{%
		\ifthenelse{\equal{\upm@reserved@a}{=}}{%
			%protected
			\global\upm@spec@modifier@has@publicfalse%
			\global\upm@spec@modifier@has@protectedtrue%
			\global\upm@spec@modifier@has@privatefalse%
		}{%
		\ifthenelse{\equal{\upm@reserved@a}{\#}}{%
			%protected
			\global\upm@spec@modifier@has@publicfalse%
			\global\upm@spec@modifier@has@protectedtrue%
			\global\upm@spec@modifier@has@privatefalse%
		}{%
		\ifthenelse{\equal{\upm@reserved@a}{-}}{%
			%protected
			\global\upm@spec@modifier@has@publicfalse%
			\global\upm@spec@modifier@has@protectedfalse%
			\global\upm@spec@modifier@has@privatetrue%
		}{%
		\ifthenelse{\equal{\upm@reserved@a}{s}}{%
			%static
			\global\upm@spec@modifier@has@statictrue%
		}{%
		\ifthenelse{\equal{\upm@reserved@a}{c}}{%
			%query / const
			\global\upm@spec@modifier@has@consttrue%
		}{%
		\ifthenelse{\equal{\upm@reserved@a}{l}}{%
			%isLeaf
			\global\upm@spec@modifier@has@finaltrue%
		}{%
		\ifthenelse{\equal{\upm@reserved@a}{a}}{%
			%abstract
			\global\upm@spec@modifier@has@abstracttrue%
		}{%
		\ifthenelse{\equal{\upm@reserved@a}{r}}{%
			%isRoot
			\global\upm@spec@modifier@has@roottrue%
		}{}}}}}}}}}%
		\expandafter\upm@spec@func@modifiers@scan{\upm@reserved@b}%
	}%
}

%-----
%\upm@spec@param@modifiers{modifiers}
\newcommand{\upm@spec@param@modifiers}[1]{%
	\upm@ifnotempty{#1}{%
		\ifthenelse{\equal{#1}{out}}{%
			%out
			\upm@spec@lang@modifier@out%
		}{
		\ifthenelse{\equal{#1}{inout}}{%
			%inout
			\upm@spec@lang@modifier@inout%
		}{
			%in
			\upm@spec@lang@modifier@in%
		}}
	}%
}

%-----
\def\upm@spec@trim#1{#1}
\newcommand{\upm@spec@splitparams}[1]{%
	\upm@ifnotempty{#1}{%
		\upm@spec@firstparamtrue
		\@for\reserved@a:=#1\do{%
			\ifupm@spec@firstparam\upm@spec@firstparamfalse\else, \fi%
			\mbox{\upm@spec@trim{\reserved@a}}%
		}%
		\upm@spec@trim
	}%
}

%-----
%\begin{upm@spec@detailspec}[width]{title}...\end{detailspec}
\newenvironment{upm@spec@detailspec}[2][\linewidth]{%

	\setcounter{upm@detailspec@return@counter}{0}
	\setcounter{upm@detailspec@function@counter}{0}

	\gdef\upm@spec@detailspec@width{#1}
	\gdef\upm@spec@detailspec@title{#2}
	\gdef\upm@spec@functions{}
	\gdef\upm@spec@parameters{}
	\gdef\upm@spec@global@return{}
	\gdef\upm@spec@local@return{}

	%-----
	%\speccons[modifiers]{name}{prototype}
	\newcommand{\speccons}[3][]{\specfunc[##1]{}{##2}{##3}}

	%-----
	%\specget[modifiers]{return_type}{name}
	\newcommand{\specget}[3][]{\specfunc[c##1]{##2}{##3}{}}

	%-----
	%\specset[modifiers]{name}{prototype}
	\newcommand{\specset}[3][]{\specfunc[##1]{\jvoid}{##2}{##3}{}}

	%-----
	%\specfunc[modifiers]{return_type}{name}{prototype}
	\newcommand{\specfunc}[4][+]{%
		\addtocounter{upm@detailspec@function@counter}{1}%
		\protected@xdef\upm@spec@reserved@a{\protect\csname upm@detailspec@return@ptr@\theupm@detailspec@function@counter\endcsname}%
		\gdef\upm@spec@reserved@b{}
		\upm@ifnotempty{##2}{\gdef\upm@spec@reserved@b{\string:\ }}

		\gdef\upm@spec@reserved@c{}%
		\upm@spec@func@modifiers{##1}%
		\ifupm@spec@modifier@has@private\gdef\upm@spec@reserved@c{\upm@spec@lang@modifier@private}%
		\else\ifupm@spec@modifier@has@protected\gdef\upm@spec@reserved@c{\upm@spec@lang@modifier@protected}%
		\else\gdef\upm@spec@reserved@c{\upm@spec@lang@modifier@public}\fi\fi%

		\gdef\upm@spec@reserved@d{##3}%
		\ifupm@spec@modifier@has@static%
			\protected@xdef\upm@spec@reserved@d{\protect\upm@spec@lang@modifier@static{\upm@spec@reserved@d}}%
		\fi%

		\gdef\upm@spec@reserved@e{}%
		\upm@spec@tmp@afalse%
		\ifupm@spec@modifier@has@const\upm@spec@tmp@atrue\fi%
		\ifupm@spec@modifier@has@final\upm@spec@tmp@atrue\fi%
		\ifupm@spec@modifier@has@abstract\upm@spec@tmp@atrue\fi%
		\ifupm@spec@modifier@has@root\upm@spec@tmp@atrue\fi%
		\ifupm@spec@tmp@a%
			\ifupm@spec@modifier@has@const%
				\gdef\upm@spec@reserved@e{\upm@spec@lang@modifier@const}%
			\fi
			\ifupm@spec@modifier@has@final%
				\upm@ifnotempty{\upm@spec@reserved@e}{%
				\xdef\upm@spec@reserved@e{\upm@spec@reserved@e,}}%
				\protected@xdef\upm@spec@reserved@e{\upm@spec@reserved@e\protect\upm@spec@lang@modifier@final}%
			\fi
			\ifupm@spec@modifier@has@abstract%
				\upm@ifnotempty{\upm@spec@reserved@e}{%
				\xdef\upm@spec@reserved@e{\upm@spec@reserved@e,}}%
				\protected@xdef\upm@spec@reserved@e{\upm@spec@reserved@e\protect\upm@spec@lang@modifier@abstract}%
			\fi
			\ifupm@spec@modifier@has@root%
				\upm@ifnotempty{\upm@spec@reserved@e}{%
				\xdef\upm@spec@reserved@e{\upm@spec@reserved@e,}}%
				\protected@xdef\upm@spec@reserved@e{\upm@spec@reserved@e\protect\upm@spec@lang@modifier@root}%
			\fi
			\protected@xdef\upm@spec@reserved@e{ \protect\{\upm@spec@reserved@e\protect\}}
		\fi%

		\protected@xdef\upm@spec@functions{\upm@spec@functions {\upm@spec@reserved@c}\protect&%
			{\upm@spec@reserved@d}\protect&%
			\string(\protect&\protect\upm@spec@splitparams{##4}\string) {\upm@spec@reserved@b##2{\upm@spec@reserved@a}{\upm@spec@reserved@e}}\protect\\}%

		\global\let\upm@spec@reserved@a\relax
		\global\let\upm@spec@reserved@b\relax
		\global\let\upm@spec@reserved@c\relax
		\global\let\upm@spec@reserved@d\relax
		\global\let\upm@spec@reserved@e\relax
		\expandafter\gdef\csname upm@detailspec@return@ptr@\theupm@detailspec@function@counter\endcsname{}
	}

	%-----
	%\specreturn{description}
	\newcommand{\specreturn}[1]{%
		\addtocounter{upm@detailspec@return@counter}{1}%
		\expandafter\protected@xdef\csname upm@detailspec@return@ptr@\theupm@detailspec@function@counter\endcsname{%
			{\protect\tiny\protect\ensuremath{_{\protect\string[\theupm@detailspec@return@counter\protect\string]}}}%
		}%
		\protected@xdef\upm@spec@local@return{\upm@spec@local@return {\protect\tiny\protect\string[\theupm@detailspec@return@counter\protect\string]} \protect& ##1 \protect\\}%
	}

	%-----
	%\specglobalreturn{description}
	\newcommand{\specglobalreturn}[1]{\gdef\upm@spec@global@return{##1}}

	%-----
	%\specparam[in|inout|out]{name}{description}
	\newcommand{\specparam}[3][in]{%
		\protected@xdef\upm@spec@parameters{\upm@spec@parameters \protect\upm@spec@param@modifiers{##1} \protect& {##2:} \protect& {##3} \protect\\}
	}

	%-----
	%\specendhline
	\newcommand{\specendhline}{\gdef\upm@detailspec@end@hline{\hline}}

	%-----
	%\specstarthline
	\newcommand{\specstarthline}{\gdef\upm@detailspec@start@hline{\hline}}

	\setlength{\upm@spec@detailspec@itrn@width}{#1}
	\addtolength{\upm@spec@detailspec@itrn@width}{-\the\upm@spec@detailspec@description@width}
	\addtolength{\upm@spec@detailspec@itrn@width}{-2\tabcolsep}

	\begin{lrbox}{\upm@spec@detailspec@savebox}
	\begin{minipage}[t]{\upm@spec@detailspec@itrn@width}%
}{%
	\end{minipage}
	\end{lrbox}%

	\gdef\upm@detailspec@separator{}
	\upm@spec@showreturnsfalse%

	\ifthenelse{\equal{\upm@spec@global@return}{\@empty}}{%
		\gdef\upm@detailspec@return@section{}
		\upm@ifnotempty{\upm@spec@local@return}{
			\gdef\upm@detailspec@separator{ & & & \\}
			\protected@xdef\upm@detailspec@return@section{\upm@spec@local@return}%
			\upm@spec@showreturnstrue%
		}%
	}{%
		\upm@ifnotempty{\upm@spec@local@return}{%
		\gdef\upm@detailspec@separator{ & & & \\}
		\gdef\upm@spec@reserved@a{ \upm@spec@lang@except@for:\protect\upm@spec@local@return}}%
		\protected@xdef\upm@detailspec@return@section{%
			\upm@spec@global@return\upm@spec@reserved@a%
		}%
		\upm@spec@showreturnstrue%
	}

	\ifthenelse{\equal{\upm@spec@detailspec@title}{\@empty}}{
		\gdef\upm@spec@reserved@c{}
	}{
		\gdef\upm@spec@reserved@c{\hline%
			\multicolumn{4}{>{\columncolor{backtableheader}}l}{\color{fronttableheader}{\large\textsc{\upm@spec@detailspec@title}}} \\%
		}
		\gdef\upm@detailspec@start@hline{\hline}%
		\upm@spec@showdescriptiontrue%
	}

	\upm@spec@showparamsfalse%

	\upm@ifnotempty{\upm@spec@parameters}{%
		\ifupm@spec@showdescription%
		\gdef\upm@detailspec@separator{ & & & \\}%
		\fi%
		\upm@ifnotempty{\upm@spec@functions}{%
		\gdef\upm@detailspec@separator{ & & & \\}%
		}%
		\upm@spec@showparamstrue%
	}%

	\vspace{.5cm}\noindent\begin{tabularx}{\the\upm@spec@detailspec@width}{|clr@{}>{\raggedright\arraybackslash}X|}
		\upm@spec@reserved@c%
		\upm@detailspec@start@hline%
		\ifupm@spec@showdescription
		\multicolumn{4}{|X|}{%
			\begin{tabularx}{\linewidth}{@{}lX@{}}%
			\upm@spec@lang@description: & \usebox{\upm@spec@detailspec@savebox} \\%
			\end{tabularx}%
		} \\%
		\hline%
		\fi
		\upm@spec@functions%
		\upm@detailspec@separator%
		\ifupm@spec@showparams%
		\multicolumn{4}{|X|}{%
			\begin{tabularx}{\linewidth}{@{}l@{}lX@{}}%
			\upm@spec@parameters%
			\end{tabularx}%
		} \\%
		\fi%
		\ifupm@spec@showreturns%
		\multicolumn{4}{|X|}{%
			\textit{\upm@spec@lang@returned@values}: \newline%
			\begin{tabularx}{\linewidth}{@{}lX@{}}%
			\upm@detailspec@return@section%
			\end{tabularx}%
		} \\%
		\fi%
		\upm@detailspec@end@hline%
	\end{tabularx}\vspace{.5cm}%

	\global\let\@arraycr\upm@arraycr

	\global\let\upm@spec@detailspec@width\relax%
	\global\let\upm@spec@detailspec@title\relax%
	\global\let\upm@spec@functions\relax%
	\global\let\upm@spec@parameters\relax%
	\global\let\upm@spec@global@return\relax%
	\global\let\upm@spec@local@return\relax%
	\global\let\upm@detailspec@return@section\relax%
	\global\let\upm@spec@reserved@a\relax%
	\global\let\upm@spec@reserved@b\relax%
	\global\let\upm@spec@reserved@c\relax%
	\global\let\upm@detailspec@separator\relax%
	\global\let\upm@detailspec@start@hline\relax%
	\global\let\upm@detailspec@end@hline\relax%
}

%-----
%\begin{detailspec}}[width]{title}...\end{detailspec}....
\newenvironment{detailspec}[2][\linewidth]
{%
	\upm@spec@showdescriptiontrue%
	\gdef\upm@detailspec@start@hline{\hline}%
	\gdef\upm@detailspec@end@hline{\hline}%
	\begin{upm@spec@detailspec}[#1]{#2}%
}
{%
	\end{upm@spec@detailspec}%
}

%-----
%\begin{detailspec}}[width]{title}...\end{detailspec}....
\newenvironment{detailspec*}[2][\linewidth]
{%
	\upm@spec@showdescriptionfalse%
	\gdef\upm@detailspec@start@hline{}%
	\gdef\upm@detailspec@end@hline{}%
	\begin{upm@spec@detailspec}[#1]{#2}%
}
{%
	\end{upm@spec@detailspec}%
}

\endinput