OpenConfigurator - A Practical Approach
to Configurator Implementation
!
"
#$%& '(#'
#%)*+%%,-
'%)*+%%./%0
1*%%- +"
Abstract
.2 "
" "2%3
.2"
.%4"2 ""
56"
" .%
! 2
2 "!"2 6%
47 "5"%
42 22"
! %
4 "!22
!. %89
/2!
%4 &+"!2!
22! 5"
%4!5"
%
4 "!!/33 /+&21
92" %: .
2"%,2
"6262 ""%
9" ©'(#'2"
Table of Contents
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #
#%#%,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;
#%'%,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
#%$%96%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ?
#%;%9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% F
#%<%4%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% F
'%+9.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$
'%#%++9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #;
'%#%#%+9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#;
'%#%'%, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#<
'%#%$%9.++9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#?
'%#%$%#%9.&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #@
'%#%$%'%9*9,+2+
29.+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#F
'%#%$%$%+9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #G
'%'%9++9.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '(
'%'%#%+8=8>+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '#
'%'%'%+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ''
'%'%$%+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ''
'%'%;%,+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '$
'%'%<%+9. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'$
'%'%?%,9.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'<
'%'%@% "9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'@
'%$%+9.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 'F
'%$%#%,9.&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'F
'%$%'%+9.9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% $#
'%$%$%, &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$$
'%$%$%#%++-+7%%%%%%%%%%%%%%%%%%%%%%%%%%$$
'%$%$%'%+&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$$
'%$%$%$%,"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$<
'%$%$%;%8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$F
'%$%$%<%++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$G
'%$%$%?%8, +-&%%%%%%%%%%%%%%%%%%%%%%%%% ;#
'%$%;%3&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;#
'%$%;%#%,, -+7%%%%%%%%%%%%%%%%%%%%%%%%%%%%;#
'%$%;%'%,9.93"8!%%%%%%%%%%%%%%%%%%%%%%%%%;'
'%$%;%$%+)4 +9.%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;$
'%$%;%;%9-4 ,9.%%%%%%%%%%%%%%%%%%%%%%%%%%;;
'%$%<%, &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;?
'%$%<%#%41" +A9+B%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;@
'%$%<%'%4 +A+B%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;@
'%$%<%$%4++9.%%%%%%%%%%%%%%%%%%%% ;G
'%;%&&36%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%<(
'%<%"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <'
$%9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%<$
$%#%+,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <;
$%#%#%9*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <<
$%#%'%&*99%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%<F
$%#%$%9*-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%?(
$%'%+9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ?'
$%'%#%9+9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%?'
$%'%'%+9 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%?;
$%'%'%#%4)9 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ?;
$%'%'%'%49 +4+%%%%%%%%%%%%%?<
$%'%'%$%49 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ?@
89 &+&9
$%$%+9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%?F
$%$%#%4-7%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @(
$%$%#%#%49 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@#
$%$%#%'%&-7%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@$
$%$%'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@$
$%$%'%#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @;
$%$%'%'%=-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@<
$%$%'%$%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@
$%$%'%;% &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @F
$%$%'%<%8%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@G
$%$%'%?%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%F(
$%$%$%9 .%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%F(
$%$%$%#%&96%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%F$
$%$%$%'%"3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%F;
$%$%$%$%, 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% F@
$%$%$%;%9 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%FF
$%$%$%<%&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%G?
$%$%;%1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%GF
$%;%"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% GG
;%, "9.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #(#
;%#%489 , "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(#
;%#%#%,9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #('
;%#%'%9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(;
;%#%$%8&9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(?
;%#%;%& 89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(@
;%'%, &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #(F
;%'%#%8C8+, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #(G
;%'%'%+,/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%###
;%'%$%+ ,!/&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##'
;%$%4)9 ,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##?
;%$%#%3)9 ,,,%%%%%%%%%% ##G
;%$%'%,, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#'(
;%$%$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#'#
;%;%, 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #'$
;%;%#%, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#';
;%;%#%#%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #';
;%;%#%'%&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #'?
;%;%#%$%+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#'F
;%;%'%+, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$(
;%;%$%9 , %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$'
;%;%$%#%,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$$
;%;%$%'%9 &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$G
;%;%$%$%9 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #;'
;%;%;%, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #;$
;%;%;%#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#;$
;%;%;%'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#<;
;%;%<%9, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#<?
;%;%<%#%)99%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#<@
;%;%<%'%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#<G
;%<%9 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #?(
;%<%#%48C89 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #?(
;%<%'%369 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #?$
;%<%$%9 & %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #?F
;%?%"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#@;
<%4&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#@@
<%#%4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#@@
<%#%#%/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #@@
<%#%'%/+&+A/+&B%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#@F
<%#%$%1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #@G
<%#%;%96"C/33A9B%%%%%%%%%%%%%%%%%%%%%%% #@G
<%'%&8!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #F$
<%'%#%,4&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #F;
<%'%'%99 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #F<
<%'%$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #F@
<%'%;%36 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #FF
<%'%<%+ 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #G#
<%$%&+ *D !89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #G'
<%$%#%1 9 %%%%%%%%%%%%%%%%%%%%%%%%%% #G'
<%$%'%+ 9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #G;
<%$%'%#%E )9 ,%%%%%%%%%%%%%#G;
<%$%'%'%& ,%%%%%%%%%%%%%%%%%%%%%%%%%%% #G<
<%$%'%$%" 8%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#G<
<%$%'%;%D !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#G?
<%$%'%<%D !9 & %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '((
<%$%$%9 + %%%%%%%%%%%%%%%%%%%%%%%%%%%% '('
<%;%+ *36 89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%'($
<%<%"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'(;
?%3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'(@
?%#%9"*19 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'(@
?%#%#%,"91%919"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '(@
?%#%'%,"91%5+- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'(F
?%#%$%41,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '(G
?%'%4),9 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'##
?%'%#%4 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'##
?%'%'%&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '#'
?%'%$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'#;
?%$%9 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'#?
?%$%#%9 E!19 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '#@
?%$%'%9 19%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '#G
?%$%$%4 - 9 3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%''(
?%$%;% D%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%''#
?%$%<%& 37%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '''
?%$%?%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%''$
?%;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'';
?%<%"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%''<
@%"8%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ''@
@%#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ''@
@%#%#%, ""%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%''@
@%#%'%9.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'$(
@%#%$% D%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'$$
@%#%$%#% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '$;
@%#%$%'%D%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'$?
@%'%8%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'$@
@%'%#%9+=9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'$F
@%'%'%- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'$G
@%$%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ';(
&%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%';$
1%36,*1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'<#
1%#%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '<#
1%'%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'<$
9%89 &+=+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'@#
1 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$##
List of Figures
#%#%,4*9,9.+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% $
#%'%96D%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @
#%$%4%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##
'%#%9.&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#@
'%'%99,+2+29.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#G
'%$%8!9++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '#
'%;%9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ';
'%<%,+,9.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '?
'%?%8!E"9& ,9.%%%%%%%%%%%%% $(
'%@%9+9.+ 3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% $#
'%F%)4","%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$<
'%G%4",.+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$@
'%#(%8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$G
'%##%,,8, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;(
'%#'% ,9.53"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;$
'%#$%+96+9.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;?
'%#;%, ,6+9.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;F
$%#%+9+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <;
$%'%1),,9 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%<<
$%$%91%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%<?
$%;%9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <F
$%<%)9 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ?;
$%?%9 4+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%??
$%@%9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ??
$%F%9 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ?@
$%G%+9 >"3,9.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ?G
$%#(%49 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@#
$%##%8!,9 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @;
$%#'%, 169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% F'
$%#$% 9 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% F?
$%#;% :9 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% F@
$%#<%)&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FG
$%#?%-1!9 4"9 %%%%%%%%%%%%%%%%G(
;%#%489 &%%%%%%%%%%%%%%%%%%%%%%%%%%%#($
;%'%8!89 , "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(;
;%$%8!8, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #(?
;%;%368C8+,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ##(
;%<% &,,),,%%%%%%%%%%%%%%% ##;
;%?% &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ##;
;%@% &, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##?
;%F%4)9 ,H1H9 +%%%%%%% ##?
;%G%-)9 ,-%%%%%%%%%%%%%%%%%%%%%%%%%%%% ##F
;%#(%,:9 )9 ,-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##G
;%##% &9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#''
;%#'%--9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #'<
;%#$%--&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#'@
;%#;%--+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #'G
;%#<%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$;
;%#?%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #$<
;%#@%99 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$@
;%#F%99%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$F
;%#G%9,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$G
;%'(%9&4"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #;(
89 &+&9
;%'#%, 16%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#;;
;%''%--94"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #;<
;%'$%9:&:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #;?
;%';%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#;F
;%'<%)89 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#<@
;%'?%48C89 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#?#
;%'@%&+9 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #?'
;%'F%9 ,9.1A36B%%%%%%%%%%%%%%%%%%%%%%%%%%#?$
;%'G%#*.,& %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#?;
;%$(%'*14"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #?<
;%$#%$*&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#??
;%$'%;*D%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #??
;%$$%<*37&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#?@
;%$;%?*37%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#?@
;%$<%@*9 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #?F
;%$?%9 ,-8C%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#?F
;%$@%9 +!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#?G
;%$F%9 +9.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #?G
;%$G%-!9 242)9
,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#@(
;%;(%& 44"0"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#@#
;%;#%3640"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #@$
<%#%&8!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #F$
<%'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #FG
?%#%91%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'(G
?%'%,:9 1,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '#(
?%$%),9 &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '#$
?%;%,9 D%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'#;
?%<%0& E %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'#<
?%?%36")9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'#?
?%@%9 9 E!9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '#@
?%F%9 4"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '#F
?%G% 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'#G
?%#(%.9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%''(
?%##%D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%''#
?%#'%++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'''
?%#$%9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%''$
@%#%989 !, 169
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'$#
6
List of Tables
;%#%, !8C9+, 9%%%%%%% #(G
;%'%, !/9)9 ,%%%%%%%%%%%#'#
;%$%, &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #';
;%;%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#'<
;%<%93%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#'?
;%?%&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#'F
;%@%&3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#'F
;%F%+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #'G
;%G%+3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$(
;%#(%+, 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$(
;%##%9 , 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$'
;%#'%4"&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #;G
;%#$%&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #<(
;%#;%&&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#<(
;%#<%+&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #<'
;%#?%1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#<;
;%#@%&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #<;
;%#F%9 & 4%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#@#
<%#%)33931%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #G(
&%#%: =&99%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ';;
&%'%9"9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%';<
&%$%9"9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%';?
&%;%"9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%';F
&%<%969%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%';G
6
6
List of Examples
;%#%36/1,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ###
;%'%36"& %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##$
;%$% &9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##<
;%;% @Component&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#'<
;%<% @Attribute&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#'@
;%?% @Part&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#'F
;%@% @Product&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #$'
;%F%, 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#$;
;%G%, 9 2+.9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #$?
;%#(%, 99%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #$F
;%##% @Calculated&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#;'
;%#'%@Configured&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#;$
;%#$%364"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #;G
;%#;%36&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #<#
;%#<%36+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #<$
;%#?%36%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #<<
;%#@%9& %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#<?
;%#F%9& ,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #<F
<%#%+ 36%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '($
@%#%, 9.+!89 9%%%%%%%%%%%%%%%%%%%%%''F
6
#
1
Introduction
A Bit of History
0 ! . % 9
!%4
7.!!!""
%4! !!
I:'((?2%'J%
D62!
"" .#G"%&
"2!
"!
"'(" %
7 !2!"
52 " !
%&!
%4
"!!A%I0K'((#2%GJB*
#% + 2
'% 2
$% !2
;% %
The Market Shift
0!2*HI%%%J
42""
"
I"JHI1'((<2%#(J%!"2
62"A%I-
!'((G2%'$J2I:'((?J2I0K'((#2%GJ2I+'((?JB*
9R#%R
'
0 "6
2!!!%0!2!"5
!"A
B%47 5
" %
0 ,
2
" !! %
0 4 "!
%- !
"""%4
%
97"!
525
!%
0 2 2!
%4"277"
6" I-'(#'J%
0 4"
%4"7" 7
% 2."2
"52
"%
L 52
L "A2
2 B2
L 2
L !!7""
%9!
" %
3 ..2
"2"%3"
""!%
&72 " "
I0'(#(J%4!
"%4
" !7!
62% %2" =%
0!2 !" "
I:'((?2%'J%&+)*H"2
!M"C!6"!"!%HI+#GGG2%@?J%!2
"!"%
R#%#2N,4*9,9.+O
"A%I:'((?2%'JB%
$
Figure 1.1. Market Trends: From Custom-Made to Customized Products
4. 7
"I>'(#(J%6
27!
.!"5
I'((GJI-#GGFJ%47!
" I,'(#'J%&
!! 2
""*2
%4
I1'((<2
%'J%
Business Today
4"5 7"
""I:'(#'J%"2
2 %
" %0!2
".26"5
2 "
"%2 2
""
%
. 2
" ! " 7
%E"
52"7
.5%
"
"52"2
9R#%R
;
%D 257
2! "
%9 "2
7 !%+
%%%
L !2';=@
L 7!6! 2"6
L A "B 7 7
H HI:.'(#(J
L "
L 272
22!2%"
2 ""
" .%4" !
2 2 %
1.1. Motivation
3"62
! ! "%3
!"!2"
7"6%42"
22 % 2
5"!
"22!22
"%
E2""5 HH2
"%+
"!! .2!%4
! 6!2
" "%,2"
"" 2
! 2%3!2
262
!%97"2 "
"%
) 62
"!!
56"2!""%
D 2" "
" 2!!2
6%4"2 2"
%
1.2. Mission Statement
!2!!
2!.!6.
%1" 2 2
. 2"
C "
" %
,
<
D ! /A
"/33B "" 2
" %4 !27
6 %2!
2 %
8 /2!7
" 7" "26"2 "
"%D !!!2!"
"6 2
! %4!"
." "
!"%
Concrete Objectives
4 " !.
"! *
0 4 "
2"" %
0 4 "!"
*"5"%
0 4 " !6 2
!"!%4" A% %2/
33B2"A% %2
B%
0 4
"2 *
L!0 4"
! 26/C
!%
L0 4!2.
C7"26%4"2
"" !!C56"%
L!""0 1 66
27"
%
L0 "2
"""5!%3
"2 2!4"%
L#0 4""
"6 2
7"""%,2 "
"%
9"2!2!5! *
#% $0 !2!
.
9R#%R
?
C2%D!!
.!6/ !%"2
! 2!!
!*
L
L C=
L A2B
L /2! !/33#2"*/+&'A
=B1A
B
'% $ %0 1
2!" !!
A B %4
."! *
L !HH
L 2&+$
L ! &+ &+
L 5 "6 +;
L ""/33?!A9<2/+&21B
$% 0 2!!
" .6 %3"2!52"2
A !B
2!" %4
.*
L 5!" &5+2
"!!!
L 6*%4"!
5/1
L *04,:<=9=/229
&+
4!!%4
.!6"%97"2 !2!
!" "=H89
"HH89 H%
1.3. Context and Scope
4 !7
2"2
" %1" ". .
2!5"7"
.%: 62!
2!
% R#%'2N96DO6!*
#&%,##
'&%,!+
$&%! "
;&%%"
<&%6-""C
96
@
Figure 1.2. Context of this Work
2!
2! 6!%D!
*22
%42!2!"%
4 !*
0 82!2 !
!. "
"%29R'2
9R$2!"%
&0 9 !
! 22! !"
! .
%4"!"
9R'229R$29R;2
%
$0 9 !
"%
9R;229R<2 !
"9R?2#$%
1" 7 2! !
7! .%2!
!2 !"
2!2
%
! 2!!
!%45!*
L !.
2 .C
A"9R'29R$2B%
9R#%R
F
L A""B.
! %2
! "A"9R;2
B%
L ""!!2!
%45
! ""A"
9R<2 !"B%
L "2""
!%D6
! 2
!A"9R?2#
$B%
L .! !6
A"9R@2%B%
1.4. Challenges
D89 7!
% !5"!
!"89 %2 2
. !2! *
'%())0 4 8
9 "!6
"%"27!89
HH22%R9
7"2!5%289
HH2" !%
E2! 7"%
# % "
0 4 89 !6
!7"
%D!!! /33
"! 6
"2! ! 2! !
5%2!"6 2!!
R
76%
82!.6
!" %2!5H
H2 %0!26
6"
%D22
6!%
1.5. Thesis Structure
0 !AB A&B
"!2 C 2!!
"AB26*
4
G
0*(0 2!!
''%D!
.
%7!"
*
L D.!"P
L D5 .!
P
L D "!.P
4 .
!""! %4! "
2.
!%
0+(0 4"(
6"%D! .
272!"
%42!!
2 ! %
&%+72!"
*
L 0!.! "P
L D P
L D "!""P
L D P
0 2! %,
2.6"""
%
0,(0 9;!
" 2%
D )!*2!!. "
.%4!5
%E62!5
2! 22
2%"2!!
2"!2"! 6
%1" 2"5!! 7*
L D89 !
P
L D89 !!
"P
L 0!.!89 5P
L 0!!
P
0-(0 9<2! )
89
!%D! !2 !
%42!589 5
9R#%R
#(
! "2!!&++%
2"5!! 7*
L D ! 89 !
!P
L 0! !2"P&!
!5 .P
L 0! !!2"P
L 0!!6P
3"2!7**
+
0.( 0 4"2
%D56"
. &5+%
4"2!5. 204,:< 89
! "%9?!!! 7
*
L , "* ! ! .
89 5 P
L 0!04,:<2
!P
L 0! 2.!89 "P
L 89 2C7"P
& 2"2!7*
+
0/(!"#0 2!
" 2!89 "7
"%,2!!.
!
%42!%"2!5
!" Q%47"6!
"*
L 89 5 7
7"P
L 0!!.P
L D !"P
L 0!!P
R#%$2N4O!2!%
4
##
Figure 1.3. Thesis Structure
3!!"2 %
"5"2""!C"
!5 %47%
E!25 !"%
#'
#$
2
Product Customization
" "!2"5
" A B
! % 2! "
"%
& 1%H. "
57HI1'((<2%##J%
2!!.=
!!7!%D5
.%42!5
!" "%4
*
L 2
L 2
L 2
L .. %
E62!5.
.
%"2!5!
%367"".
%
4! !
.%4"
"
C%2
""
. %
9R'%R+9.
#;
2.1. From Products to Product Configurations
2!5.
%
2.1.1. Products and Components
Products
4HH"6 22
2!!"6%
2!"2"
2H H#%
0!256
%
2""
2"""2 "
!27!I1'((#J%& > I> '(#(J2
"ABH2
C =
H E?@FG%826"!
A!R'%'2N
9++9.OB%82
"E7
" !A%I> '(#(2%?JB*
1 &.
./%
2> ! HH
!2!!*
L "" 2!2
L 2
L 2
L A"BA"B2
L .
L %
!2%&
"H !
AB!HI0'((F2
%$#J%
Components
+'%422
%+"2
!*
&23 &0A
B2!."
!""A
=B%
#*==%!"% =!=+2/"'G2'(#'%
' *==!!!%%!%%==6%PVW$'(UW+UVW;';?;$@1;?;#$@$@;''$($<$?
$$'$;2/"'G2'(#'%
,
#<
12HHH"H6
!*A"B
22 %2
!"
AB%2"
!"" %
4
2!R'%$%$%$2N,"O%
2.1.2. Variants and Variant Management
Variants
& E#GG#2"C
""! IK'(((J%
4C "2 "2
%4
$%
+ "%D!
R'%$%$%$2N,"O%!25
!""A%I+'(($2%''$J2I&#GG?2%;<J2
I9#GG#2%<<J2I0#GG@2%@<JB*
!"0 -"%
.""6. 6"%
0 -
!%4 "
""22"6"
%97"2."
. "%
Variant Management
42 2 !
2;%9
722 %
AB25
"
5"
5%4"
" !
%4!2H!"H*
2
""%
9 7!A
B6"* " "
5"% 2
""%2
! 2!"7
A!2B2
$ *==!!!%%!%%==6%PVW$'(UWUVW$@;'$$@1;#$#;<$<$''$<$;;$
;<'$;2/"'G2'(#'%
; *==!!!%%!%%==6%PVW$'(UWUVW$@;'$$@1;#$#;<$<$''$<$;;$
;<'$;2/"'G2'(#'%
9R'%R+9.
#?
"5 "
%E"A=B!
6" *2
"2%4
7"2 A B2
! !
! "%82
2%
2
%82
%82
2!7!
%"2
2 %9"2
!225
"2! " 6
CA%I+'((#JB%& "6
""6
"%5 !6
.2 %
&2"..
76" ""%0!2:
%I:'((?2%FJ !"
*
40 8
"<S#<S 7"%&F(S
"!#S%97"2 6"
" %
'0 97"
"" %426"
"""%
2.1.3. Customized Products and Product Configurations
&2
%6""
2!7"
I0K'((#2%<J%I'((?J"
A%I> '(#(2%GJB*
0 4
."!"%
0 D
2.%
0 4".
7%
" 5
<%"
<*==%!% =!=9. 2/"'G2'(#'%
9.++9
#@
.A.BI:'(($J%&
6.2
5"!
!
I+'((#JI+'((;J%
2.1.3.1. Customizable Areas
3"2
""A! .
2%I+'(($JB*
L "
L A2"2B
L A"B
D 7".
A% %2B26 A% %22%B
.%:%!
A%
I:'((?JB*
Figure 2.1. Customizable Areas
4 R'%#2N9.&O*
5"0
""%,!
6 2!
"! %
9R'%R+9.
#F
1"62:%! %
60 D "AHHB
AHHB2.
%D
2
""A% %2 B2
"
A% %27 B%
0 D.
""!
%4%
10 + !.
22!
A% %2"
!2 % "B%8
2
6%+ "7
%
0 &2!2"
A% %226!"2%B%4.
%
$"0 "2 6
".%-)
6"
A% %2 B%D
267"!%
1)! !.%0!2
"%"2
27
%
D.2"
6" 2!!"7
9R;2%4
" %
2.1.3.2. Comparison: Custom-Made Products, Variant Series Prod-
ucts, and Customized Products
" A R'%;2
N9 OR'%'%<2N+9. OB2
! 2 %
R '%'2 N9 9, +2 +2 9
.+O "
I:'((?2%#(J*
9.++9
#G
Figure 2.2. Comparison of Custom-Made Products,
Variant Series Products, and Customized Products
4!
. 6"*!
""2.
2"!!62
7%"2!2
."
.I:'((?2%##J%
2.1.3.3. Product Configurations
!!!".%4
57!
7.I:'((?2%GJ%D
72
%
4 %&
2
!2! %
4 "
""!"% 2
2!2!
"!.%
+ " !
A "B!C!%4
2 2
7AR'%$%<%$2N4++9.
OB%+I+#GGF2%GJ
9R'%R+9.
'(
!%D2!5
6"
" A
R'%#%'2N,
OB%+ 7"6"
%9
R$2!!%
0 !2!!
"%
2.2. From Classical Production to Product Cus-
tomization
4
%4AR'%#2
N++9 OBI'((<J%
H9H" 2. %
&9R#2"2 "
"%!2"57!
%>! !A"
"B"%422"7
2!
.%
! 2!!6HHAI> '(#(2%
#$JB!".2!!
!%D!.2
." !%
R'%$2N8!9++O!
%
+8=8>+
'#
Figure 2.3. Overview of Common Production Processes
2.2.1. Per-Order/One-of-a-Kind Production
A2B 27
%4"2
?%4!
"572!
76"%
& > I> '(#(J2""
7" .%&
7"6AI>T'((<JB2
"5"7%2
7 !
%+
22 "%
?*==%!% =!=3. 2/"'G2'(#'%
9R'%R+9.
''
2.2.2. Series Production
%AB
.%."72
2A2B
%5"! 22
%8 2
7@%
" !
%4 "!
"!
.A6 B%4 2"
27!!A
B%
& 26"
"I&'((;J2!!">
.I> '(#(2%#$J%36
""2%
2.2.3. Variant Production
D" 2
! ""2 "2
F%02
"%
2
%
"%3622
%
&"> I> '(#(2%#$J2"
.!
AR'%$%$%;2N8 OB%
"2
.%02./%4
%8!2
""
2> .
%02
%4./ %
" 22
!7
"%E2!
26 "
!%
@*==%!% =!= 2/"'G2'(#'%
F*==%!% =!= 2/"'G2'(#'%
,+
'$
2.2.4. Mass Production
4 ""2!
" .%4"26
"%,."G*
$0 "" C.2
""6 %0!2"
""%
0 4.!%4
.2 ".!%
570 "
7 !.2!
7"%
80 4."
! 2! "
"%&"!
"0""'(""
<((S%46"H4H!!""'$<
"#'F%
40 4 7
!
%
D!4"5H, HA
H4"HB!!"'("%
90 "2
"
%
:%03A2
BA2
.B!2!
! %
4 H22
!! !""
%HI1'((<2%GJ% 2
" "2
%82"6"
2!!"".%
36 %
2.2.5. Product Customization Strategies
1%H "
57HI1'((<2%##J%4 .
"%9
2. "A%
I'((#2%#JB%
G*==%!% =!=, 2/"'G2'(#'%
9R'%R+9.
';
!2. "
"%& "
"2
A%% !B
A%% B 7I'((?2%
@J%9 ..
2"A#(#<S
B%
2.!
%D. A%%
2R'%$%;%;2N9-4 ,
9.OB2. 5
AB%4 2
"6 AR'%$%;%$2N+)4 +9
.OBI'((?2%#'J%
+"2. ."
5% 2
!*
Figure 2.4. Customer Involvement Strategies
60 "2"5
%4""""
A9-,B%
4 2
AI'((?2%FJB%
0 4 = "
%0
7"%D6
.2""
6%
0 4"!
6*" 2
!"" %2
"!
" %4 "
H8HI-!'((GJ%
,9.
'<
".2
""5*
1%H "7
"%HI1'((<2%$J4
%4
HHI4#GF;2%'@<J%4
"
" 2.
A%I+'(($2%'(FJB%2
I+'(($2%#<;J% 2 "
2!!"
%
2.2.6. Mass Customization
4. #GF(!
"H+H#GF@I#GF@J%1"#GG'2
+5H,9.*4E!19
HI+#GG'J""
I1'((<2%;(J%
"2
!"I+#GG'J%DHH
.""
2.%
2.2
A +!
"I+#GF(JBI+'(($J*H4
." 5
"%HI1'((<2%'J%
8.
! "
7I-!'((GJ%"
!2*.
" . "
AR'%$%'2N+9.9OB%
2.I+'(($2%'(@J%
& ""+*,.
L " 2
L !6"" 2
L 2 2!
"%
4 .
2%I+#GGF2%?<J
9R'%R+9.
'?
Figure 2.5. Main Principles of Mass Customization
4.A R'%<2N,+,9
.OB -!+A%I-!'((G2%''<JB*
0 9.
5 %4
! 2"
!2 .%
$ 80 1" . 2
. %
9.2"
.%
10 2
6"=%0!2
!2H HA
R'%$%;%'2N,9.93"8!OB%&2
! .!
"%&2.
!"
%
0 4"
262!.!
%2
""!%4!
2!".
%
& 1%H !.
.%HI1'((<2%'J"2"
.6".
. 2
%4!
.ABA
B" ".
! 5A%I+'(($2%#G#J2I0K'((#2%
"9
'@
#(JB%22
.2
" 52!H" 5
!"HI1'((<2%66J%
R'%$2N+9.O!!2!
"."%42!!
2 %
2.2.7. Strategy Comparison
+. 2
"2I+'(($2%'(@J%
2 "+".2
. 2!!"!"+5
! %
92. "C
.""C2*
L 2
L 76"
L
L A2!2%B
2. "2"6
!" !2
%+
H..H!!R'%$%;2N3
&O26".2
. %9!
2! "*
"!22!
"!"%
2.
%
&" "
%2. 6
6 7
7 A%I0K'((#2%
##JB%2
!2!."
)56%4
!"2"2" %
&"2.2
%4 2"!A!
!R'%$%$2N, &OB%,2
"!
5%2
2
%4 %
& !7 2
%
"
%6
9R'%R+9.
'F
"
"%,. 22
%2
.." 7 2"
7%& +2.
6"2
A%I+'(($2%'(F'#(JB%
D5!"%"
. "! ."27
""* 2
6"2
27%D!
!
"".%
2.3. Product Customization Implementation
9. 6
.%4
!%
42". "2
".%
. A%I:'((?2%##JB*
L !
L 2. .
L !"
L .! " !
L .6 .
2.3.1. Mass Customization Achievement
2 .
."2#(%+6' .
I+'(($J##*
0 .25
%97"2".%
2
2"%
A6.B7"
!26"!5!%
2+! 2. *
#(!I1'((<J2%#'%
##4"I1'((<J2%#@%
,9.&
'G
L0 !.
2"%
L1 0 " .
."%
L0 8 . .
%
4 0 2".
6 % 9 "
"%97"27
"
2!""%47"
5"%
+ ! . *
L "0 3A B
A"2 B.!
"%&.%
L0 9. .2
%
L5"0 6 ""
..! %
2 "2"62
%2
. "%57""
.%
. ""
"62" .
"! .%
,2""2!"2
.%1
%!
.I1'((<2%$(J% R'%?2N8!E"9
& ,9.O!"7
"".%
9R'%R+9.
$(
Figure 2.6. Overview of the Necessary Conditions for Achieving Mass Customization
1 .%D
!R'%$%;2N3&O%
-!7
!! "22
!. %D!
R'%$%'2N+9.9O
R'%$%$%;2N8 O%
"26"2!!
R'%$%$%<2N++OR'%$%$%?2
N8, +-&O%1"2
".%9."
R'%#%$2N9.++9 O!!
R'%$%$%'2N+&OR'%$%$%$2
N,"O%""
7.%42!
%3"2
"57%D!
9R$2%
- 2
)"R'%#%'2N, O%%
! H" "
7HI1'((<2%;(J%2!
" 5%D!R'%$%$%'2
N+&O%)!R'%$%$%?2N8
, +-&O%"2"
7""! 5
2 2%
+9.9
$#
62!! !.
%D5 2"
7 " .
%D52"2. "%
2.3.2. Product Customization Value Chain
+. "."!*
AB
AB R'%@2N9+9.
+ 3O%
Figure 2.7. Value Chain of Product Customization Pursuing Enterprises
4 +
",3%+#GF(I+#GF(J%%
" ""%2
"! %
22!AB
AB%36!%4
!#'%
&2. "!
2 % A
B2.
2!." %E"
.7 A+B%
&56C
2 .A
B%
2 A-UB72
".*"
#'*==%!% =!=DS9$S1? 2/"'G2'(#'%
9R'%R+9.
$'
.2 "%
-U!.262
.2"
%4 A
R'%$%$%'2N+&OB!
2!" %
:.2 .
..!.
7!"
."%.2
-U 26!"
2!!"%:!2
HH
A%I+'(($J2%'@(B%
-2.
%4 7
A9&B%6"!
A9,B"%4
! 7
A9-,B%"2.
! A9&B"2 %&
"2"! !6 !2
A3-+B A+,B
6 %D!
!"R'%$%<2N, &O
9R$2%
4.
7AB
AB% 6 A
2R'%$%$%;2N8 OB
!"%
2"."2
2"
% 7
" !7".
%+ ! 2
!".-U%4
7
H"H%&""
""
"%
47C2!
A!!
R'%$%<2N, &OB% "2 "
."5 .
6" 5%D"7"
2!
A6B%
4 6 2!
7" !
%4
"6 .!
.%&"25
"2!
, &
$$
! 6A
(B%
D AB"
22.7
2!""""%&
2 2C
!
%
4"
C%4
%4
2
%&".2
7. .2
7 %
2.3.3. Manufacturing Aspects
2.3.3.1. Product and Production Related Prerequisites
".
%82"5
.22.
%6
2!! 2 "
6 27!6""
.%47 2
2%
82"C!
*"!
.%!2"
6 %"2
!.
%
D!"! %
2.3.3.2. Product Architecture
4./"5 %
& 1%H
"" !"!"!
HI1'((<2%#?;J%46!
%!.
"2
2C2""
I!.#GG?2%$$J%4"2"I&
#GG@J2I0'((F2%$?J*
10 4!22
!!"A
B%2"
!%
9R'%R+9.
$;
10 4!
AB. ! 22
2 2%%
AR'%#%$%#2N9.&OB%
10 .
"2 22
"22222" %
2"
2!!"
%
90 "!
2.%
R'%#%$%#2N9.&O!"%
2!."
AB2 A
0BAB%
&2 2
!! *7
"%9 "A 6"B
! "A! "2R'%#%'2
NOB6"A%I0'((F2
%#;$JB%& 2.2 " !5
2".5"%
0%""5
AI0'((F2%#$GJB%4"
"A%I0'((F2%#;@JB*
0 & 2
""%""!A!
BA!B%2""
"!22
""%
6;0 4C "
" %D
C22 ..
!C 6"
%8C""
2%
0 47 .
%0%!
A%I0'((F2%#<(JB*
L %0 52
!%
L!%0 !5
%
L1%0 5"
"%
4 "
" 5.% "!
, &
$<
"2.2
"! 6"
%&2."
%
2.3.3.3. Modularity
H+"
"" %I%%%JI,
"J""55.2
57%I%%%J+"
"7I.J%HI1'((<2%#?$J
26C2
2!!6"%E.
!#$A%IE'(('2%#'@JB*
L &"!!6""!
%
L &%
L &"%
L &!%
D".#;20%
""%4". R'%F2N)
4","OI0'((F2%$($#J*
Figure 2.8. General Types of Modularity
0 2.
%2"
%
%0 D "2
2"!
#$9I1'((<2%#?;J
#;I1'((<2%#?;JI>T'((<2%F;J!".%
9R'%R+9.
$?
%62"
HH%
0 4"H: H
"%&"! %&
"6"2!
!" %
0 2!
57%36
.!!!%
<2=30 &""
2!"
!%4"2
""%&622
!!%
D""2"6! 2
"26 %
"""2
!! *
0 +A"B"".!
"27%
0 A B!"
!"!I>'(#'J%
10 "
6!I:'((?2%;;J%
10 ""C
IK'(((J
4 22 .
.7 !
6" I'((#J%
+ 2 " " . A%
I+'(($2%'<G'?(JB#<*
0 9!)
2""%4
%
>0 &2
" %
0 9!)
22
7AB%
50 )
2!5%
#<E+7"%
, &
$@
R'%G2N4",.+ O
%
Figure 2.9. Types of Modularization for Platform Designs
The Role of Modularization
,.
.%& 12HI%%%JI"J"
6"2
""
"%HI1'((<2%<J
62.2
"!226
".
%,..
* 2"!"
.%2
" "
%2!.%,
.".
2 .%&2.
7"2
"2"%
AR'%$%$%<2N++OB"
.2"
"%+"
""2
%&"2"!. 52% %2
="!5
A%I1'((<2%#?F#?GJ2I+#GGF2%#G;JB%
3 .! 2
!%2
"
%& "A B2
A B
A2! !
9R'%R+9.
$F
"B%& 7!
!"%0!2
2"5 A%I+#GGF2
%#G@JB%
&"1%"C"
! !% %2 "2
""I1'((<2%#?GJ%
2.3.3.4. Order Fulfillment Strategies
&! .6
! %4
%1
"!R'%'%<2N+9. O%+"2
! = I-
!'(('J#?*
62630 +."%,
7%
<62<630 +."%9
HH5%
8628630 +. "
2!!%
6256(5630 +.
%9%
$62!6(!630 +.
%,6.2"
%
R'%#(2N8 O
#@%
#?4I+'(($2%';FJ%
#@"I0'((F2%'?J%
, &
$G
Figure 2.10. Order Fulfillment Strategies
32 !
52"5%!2
!5%"2
- 2
"2!7"
!A%I> '(#(2%#'JB%
2.3.3.5. Production Process Split
2."
%
D2C"
2%2 "
.2!! %
4"
CAR'%$%'2N+9
.9OB%&."
7 2
%I+'(($2%'$(J
& +27
6""
%4 !
"26"
%4! 6
" " 6"!I+'(($2
%'$('$#J%4 "2
"!"I+'(($2%'$#J*
9R'%R+9.
;(
0 4
2"%42!2
"%
0 4 "
%&7"
%
& 2 %4
!!
2!"%3
"25!.."
".%+!
2 R'%##2N,,8, O
I+'(($2%'$#'$$J*
Figure 2.11. Make-to-Stock and Make-to-Order Manufacturing Scenarios
?=2#30 2
❶%
❷2
=" 5
❸%
2 2
" .%D
" 2
" "%
*=62#630 2
2 "
3&
;#
❹%4".
❺! !%4"5"
❻%
D2" !
! %.22
!"2 " 6"!
5%E2
7"7%
+"2 A%I0
#GG?2%??#J2I+'(($2%'$$JB*
L 2
L 2
L ""2
L "2
L %
2.3.3.6. Other Manufacturing Process Related Aspects
,"6"
7 2 A B %
0!2.72
"2"AI:'((?2%?$F@BJ%
22 "9E92!
7 A% %2 2 2 B!
22 6"%4"
" 2
7"""%7%
A6 ! B!
4A" 2 2 2%9&!
M"B "
"6 A%I+'(($2%$(<JB#F%
,26"22
! A9&,B"
".AI:'((?2%
#<#JB%
"2 "62"
A9,B"2!"!
". %
2.3.4. Economical Aspects
0 .
2!!7
.%
2.3.4.1. Market and Marketing Related Prerequisites
H9 " !
"65 %!"! "2
#F6 I:'((?2%FGJ%
9R'%R+9.
;'
!7
7 HI+#GGF2%$J#G&
R'%'%<2N+9. O2..
2!
AB2AB%
2!276
".A R'%?2N8!
E"9& ,9.O2%I1'((<2%$#$$JB%
826*'(*
10 +" 2 2"%6"2
"%
0 -7""227""
%
0 "2 "% "22
"%2"%
0 92%
%
1"25!
2% %2 "2 ""2
"! !
.%
82"
.%4! A"B"
"6%&"+2
22 ".
25%
"2"*>
2!5 2"
.! !""!
I>#GG?2%;;@J%H3! !2
"!2"!
.HI1'((<2%$$J%
2.3.4.2. Mass Customization Cost-Efficiency Overview
3!. A
R#2N4,OB2" .
"" "
%4 2!!2."""
"52
22"%42
%
D2
.'#22!!:
%I:'((?2%#??J%
#G9I1'((<2%##J%
'(4+5I+#GG'2%??J%
'#6I-!'((G2%';#JI+'(($2%#?GJ%
3&
;$
Figure 2.12. Influencing Factors for Mass Customization's Efficiency
R'%#'2N ,9.53"O !
2".%D!
"%
2 "6%:!2
"2!2
2% 2. ""2
66
"%
2.3.4.3. Profit Gain Through Product Customization
2.
7 A+B 2!7
%&62
!" 6 %D!2
"%&"
""
2! "
. %
46!2"
.7" AB%
& 27"AR'%$%$2
N, &OB2""
" %2
"62!
%&"2''2! 2
2" !!%4
!275!
''4!"+I+#GF'J%
9R'%R+9.
;;
7A-!+2I-
!'((G2%';#JB %&!!R$%$%;2
N1O2 ""
5%&2
. "!2*. "
6 2!!"5
"%42"
! 7""
2% %2" 6" 6 "
%,2."
62 *
2 "
"7%82
6"!%
2 ""%
I:'((?2%#??JI-!'((G2%';(J
2.3.4.4. Cost Reduction Through Mass Customization
1" 2.
%27"6!
I:'((?2%#?F#@'J*
!0 ,"
.AR'%$%$%$2N,"OB
%1" .2
.A#%B!"
A#%B*.
!"2!
"%
!$0 &.
"
AR'%$%$%<2N++OB%&
".2
%3"2!
" "2
. " !"%D !
HH" "2
"7"%2 2
2! 6"
2". 5
I:'((?2%#?GJ%
!0 AR'%$%'2N+
9.9OB257
%4"
!%4.!
%& !!
2"2!
..%4
"2"2
%&
2! !
2 !"
A% %2&.'$
'$*==!!!%.%=2&'(2'(#'%
3&
;<
H9D1 4&1 %%%H6"
B%:!27""%
!@0 .2
! "%4"
2!
""%4 !! "
!2"2 "
%+"2!!6
A% %2$"2!67
B2" 2
"!" %&
72!22 "
%&2""
""! 7%
& 2662
%82
"572!6%
82 !6"A% %2
26"B" %
&7
62"
. %466
26 !
6" 226%
42!A% %29E9';B!
A3-+'<29&'?+,=+:,'@!2"
9,'F ,-+'G !B7%
2
."%
!
%82!
!2 ."
"!%1"22
7 "%&
7 "2
"7A
R$%$%;2N1O""
"B%& ! 2"
".57"
"2!%
"26"%!
"".26" 7
"%422
"2 !
"%
&!2. "
%97"2
';&%.7
'<&%#8
'?&%!-
'@&%- =9"
'F&%"
'G&%87
9R'%R+9.
;?
62" "2
.2"%
2!
%!27!%
72-!+56
I-!'((G2%'?$J%
2.3.5. Marketing Aspects
4 .2!!!
%+"2!!
.%62!! "
2!!"!.2%
&"R'%$%'2N+9.9OA R$%#2
N+9+OB2
%2" .
." !%
Figure 2.13. Interaction Process in the Context of Product Customization
! 2!!AB
2AB%42
. % R'%#$2N+
96+9.O!5
5%
:5 !" %
, &
;@
2.3.5.1. The Buying Process (Customer Perspective)
4"
I'((?2%#$J% !2!"
"A% %26B""2
% %2 =B2" %
!2 !"
%4"
L A% %2 B2
L A% %2 B2
L A% %2B2
L A% %2" !B2
L A% %2 B2!
L A% %2B2
L A% %2! B%
&"2"
L A% %2B2
L A% %2B2
L A% %2B
%
& 2"
% 2
"77%
42!" *2!"
!=226=
I:'((?2%'FJ%
& ! 2
%. 22
!"A%I'((?2%
#$#FJB%
2.3.5.2. The Selling Process (Supplier Perspective)
822 !AB%
4 "5 7
%4 """5
"A R'%#;2N, ,6+9.OB%-
!%6!!H;+H2!22
2!!.2"
I-!'((?2%'(J$(*
$(4! "I'((?2%#GJ%
9R'%R+9.
;F
Figure 2.14. Marketing Mix for Product Customization
10 5 5
22%
+."."
7 A+B%
109 %3"2!
5"!"! %
.2! "%
12$30 & .
%
.2 7"
!A6
2R'%$%#2N,9.&OB27
%
12 30
%-
.2"76 2
"!%0!2
! !%-
26""!
2! 2%
0 4 "
%%2"
"! 2!
%1""25
5%8"2
%"2 "
.5 6%
0 &.
AR'%'%<2N+9. OB2
!227 %& 2
!5 2
6" 7"%)
"" 2.
, &
;G
22565AI'((?2%'#JB2
%
0 75 2
7" %46"
.""!
AR'%$%$%;2N8
OB ."AR'%#%$2N9.++
9 OB%
2 !
7 ""%
"2"%&
2. 2%%
R'%$%$%;2N8 O2 %
2A% %2B
%"2!2
22 "" A%I'((?2%#G'<JB%
2.3.5.3. The Interaction Process of Product Customization
E!2!" ! 5
52!!
!%E"2!! .2
6%
-2!
2.26"
A7B2 6%D
262
""..
"%2"
C%.
!""2
"A%
I-!'((?2%##FJB%
"2!
2% )2
"!.%06
! 2%%2"
" %62"6"
%
462!"
2%& 2"
22 "%
+ !%4
6R$%'2N+9 O%
2"
%45
%,2 2!
R$%$2N+9 O%
& ""2
" %4
"!"%4
AR'%#%$%$2N+9 OB22
9R'%R+9.
<(
2%4
"72!
"%
E62! .
%D 2
%.2 ! A% %2"
" 2B2
"2!
"%
82!" %
2!
"%&62 !
7"2!5!
%,22.!
""%4"
52
27A% %2 B%
"2 A
"2% %2 B %
"26 ! 5
%2
.%
4
.6!.%
!2!!"
. %3"2!5
%12!2!5" !
.%
2.4. Application Areas and Examples
+. "%D""
2.
!7"%1'9$#1'1$'2.
!"$$*
L80 /!2 2 !.2
%$;
L80 " !.2
%$<
L8A90 4C"!
.! %$?&2"
$#&%3
$'&%33
$$4! 6*==!!!% %=2/"$(2'(#'%
$;3% %2 I*==!!!%%= "!=J2 4 /!
I*==!!!% C!%= =J2 1 1 I*==!!!% %=
=.VJ2/"$(2'(#'%
$<3% %2 I*==!!!%%= 9<GJ2 0I*==
!!!%%=%J2/"$(2'(#'%
$?3% %2 DI*==!!!%! %==99<%J2 1,DI*==!!!%!%===
= V= %J2 ,1.I*==!!!%.%==
"==V "V!==V= ==!V=
&&36
<#
. 5
". %$@8
"2"26""!
.%$F
L<A40 +.22222
%$G
L! A 0 5
2 " ! " .
"%;(8.
2%;#
L50222!
.%;'
L5%0+.!! %;$%
L4A0 D!.22
66.
%;;
L0 2.
".%;<
L0 &
%;?
3"2'$
;@%4".
"6"%
2"22!.%
4 22!!.
%
V!V %%J2 4"I*==!!!%"%==!V=
6%6J2 -I*==!!!%%==!=6%CJ2 I*==
!!!%%=+!,J2/"$(2'(#'%
$@3% %2I*==!!!%%=JA I0'((F2%#;;JB2I*==!!!%%==
= %J2/"$(2'(#'%
$F3% %2 0"I*==.%"%=J2 1.I*==!!!%.%=J2
0XI*==!!!%"%J2/"$(2'(#'%
$G3% %2 ," +I*==!!!%"%=+%J2 %%%I*==!!!%%==
==6 =J2 0;,I*==!!!%;%=J2 +I*==
!!!%%=J2/"$(2'(#'%
;(3% %2 &I*==%%== =,$''=&PJ2 I*== %%%=
= %6PW(('$'($UWUWUWUW#UVW'$'(J2/"
$(2'(#'%
;#3% %2:!I*==!!!%!%====.%J2/"$(2'(#'%
;'3% %2 9.I*==!!!%.%=.J2 4%I*==
!!!%%=J2D,66I*==!!!%!66%= %J2/"$(2'(#'%
;$3% %2 , &I*==%%==J2 E I*==%%==V=P
W2J2/"$(2'(#'%
;;3% %2 &I*==!!!%%=J2 I*==!!!%%=J2 - I*==
!!!% %=== =J2/"$(2'(#'%
;<3% %2:)I*==!!!% %==. = %J24">3
I*==!!!%%.==J2/"$(2'(#'%
;?3% %20';I*==!!!%';%=J2/"$(2'(#'%
;@3% %2I*==!!!%%=J2/"$(2'(#'%
9R'%R+9.
<'
2.5. Summary
2!5! 6
!*.%
DC22
2 " !%
E62!6""%
"22!6
! H!".H"
.%4!
!9R;2%
D 2!
%D6
22
"%D.
"2 .
9R#2"%D
".
"%2!
."2
. %&
2.! %
0 2!7H!
."HH!H%
R'%$2N+9.O2!H!
.H%D
2!! 2
A6B
A6"B%&
7 "56"2
!7 6"%62!
2!
%
4!2
2%D
"6 !.
!"%"2
!%D2 "
"557
" 5%
D!"
.%
629R$22!!%
<$
3
Configurators
9R'22 " .
%D
.%"2
AR'%$%'2N+9.
9OB2! 57%D
2.%42 2
"72"%
2"5%
"2
" "*!2
AB
.%42 !%
4 AB
!.%&2!!
6.%42!!
2 7!
%
Configuration in the Context of Product Customization
.2"
. %+"2.
2
%4 .
!AR'%#%$%#2N9.&OB2
""! ".2%4
" !6
% 2
.!2" "
%42 R$%#2N+
9+O2.!
I+'(($J*
9R$%R9
<;
0 D2
.2A
R'%$%$%'2N+&OB2!%4.
%925
22"%,2
2%
0 2A
B ! 2
AB%2
ACB
2!72
%
Figure 3.1. Development Process for Custom Products
!2 AB2
%D2
"" .%+"2!
"%! !!
%
3.1. Product Models
4 .2 A
R'%$%$%'2N+&OB %D
2"A
R'%$%$%$2N,"OB2
%+"2A
R'%#%$%#2N9.&OB!%&"2
9*
<<
2"2 2"
6%
D2 2
AR'%$%$%'2N+&OB2
""2"2
%4 "22
2"! "
67I- '(#(2%F#J%
Basic Meta Model for Generic Product Modeling
46 2
A!!R$%$%$%<2N&
O2H9 HB%E2"
L./2
L2
L
%4
A R$%'2N1),,9 +OB%4
"2
2!!"5%
Figure 3.2. Basic Generic Meta Model for Configurable Products
Product Models in the Context of Configuration
6 22
AB%!
2!!
"%
4!
! "*6"
!"!%42!59
R;2%
27
.%
3.1.1. Components: Structural Decomposition
DAB2%
9"%4"
6ABAB%
9R$%R9
<?
2.!*
� 9"7A7B%4
5"%
80 4.
2AR$%#%'2N&*99
OB%
@0 &"*
LB60. .
"M!HH%
L160 %4!"2
AB"%& 2!HH
2%
L80 "2
*% %2
C2 "C"%
:!2 26
%
0 2"
"C %#
Components in the Context of Configuration
D 6 2
"%,2
A R$%$2N91OB*!
2%&
2AB%&
2!%
Figure 3.3. Compositional Structure of a Bike
#! ![n..m]2!n!m
%&6n[n]%
9*
<@
Configuration Decisions Related to the Compositional Structure
-2
! A6
" R$%;2N9 OB'*
% 0 "2
"" %
422"6"%
% 70
&%*"[0..1]2
"5❶❷❼A% R$%;2N9
OB%
1% * " [1]2
"❸❺❽❾%
9% *"[n..m]2!n >= 0, m
> n2"67"%47"
7n7m%2!
❹❻*
% ❺2
% ❻%
% 0
&%4)*2""6
%D"5)2
%42"2
!)"
!❼%
1% !*&!
❽%
% 0
&%%0*42
!"2!2.❶❽%
1% *&!!❾%
'I- '(#(2%F$F;J2I:'((?J2I:'((?J2!%
9R$%R9
<F
Figure 3.4. Structural Configuration Decisions
D.2!R;%;%#2N
, O%4!!6
%
3.1.2. Attributes: Component Characteristics
8A2$B
% 2"
%
"2
%
&.!*
'04!%
#04"2% %22 2"AB2
%M!5A!B%
0 &"""%& 2
"[1]22! "";*
$H H22I- '(#(J27
HH2".%2
2% %2"%
;I/Y '(($J2!%
&*99
<G
L8:2304n!%n!%
L8:60 41!A!92!
!61B%
L82304.m!%m%
L860 4"A
!2!61B%
L660 36""A!9
!B%
L60 3truefalseAB%
L860 &""%
L!"23046A!9
!2!!6nB%
$0 92! %
.*
L<0 96"truefalse%
L&:0 ""2
% %2blue%
L'0 2% %2
2.53%
L0 2% %2"King Louis II."%
L!0 922% %2{blue, red,
green}%
L$0 92 2% %2
!015002[0-1500]%
L:0 92% %2
!012[0.0-1.0]%
L0 &!2% %2{[10-15]}%
Attributes in the Context of Configuration
- "2"*
@0 &.2!""
A% %2B%4
"2%
0 9.6"
A% %2"6
HH2B%4
26%
<09A% %2
!
B%4%
<&!2I1 #GG$2%#<J%
9R$%R9
?(
&9?0&!!%
0!2A% %2"
HH2HHH HB%4.
2%
10 -2"
"A% %2 B%4
%
D./".
="%
Configuration Decisions Related to Component Characteristics
4! *
% 870
&%*D"AtMostOneA7B2
"5%
1% *D"AtLeastOne2
"%
9% *D" 12
"67"% 2
!27"""""
%
%80
&%% * . 2
5%
1% *.2
%
D.2!
R;%;%#%'2N&O%& 2!!6
%
3.1.3. Constraints: Domain Restrictions
- 22!
62
%2!A"2
B2!2
662"A
R;%;%;%#2NO6B%
- ! "I- '(#(2%F;F<J*
<0 &!6
%!2!
!226true2
% 2%
?2I1 #GG$2%#<J%
9*-
?#
2" %62
%& 2
*
L:0 "2 2
and2or2not2==A7B2!=A7B2<2=<2>2>=2%
L80 ,"+2-2/2*2%A
B%
LC0 -"%
L<0 -!%
L'0 -!%
@0 D2A
B"A
R;%;%;%#2NOB%
@0& If <condition> Then <action>%D
2".2
! % true2!"
2 6%4"
2!" %
Constraints in the Context of Configuration
2"
=%
&"- 26 2
A%I- '(#(2%F<J2I/Y '(($J2I3.
'((FJB*
L D22
! %
L 9"%27
%4!"2!
"%
L -""2!"!
%
Configuration Decisions Related to Constraints
2
*
%
&%6%D2
.! %&62
.%&
". "
!%&"2!.
2! %
4%
9R$%R9
?'
1% "&6
2! "!66
%&62 "!
"
%0!2 26"!"6.
"6 %
.2!52
2%D!6
R;%;%<2N9, O2!!!62%
D5!%6
AR$%$%$%<2N&OB2
"
%3"2"2"
!!%
D! 29R;2
! . 2
2".2!%02
(7.%
"2!!
6%
3.2. Product Configuration
!!A"
B%D ACB"R'%#%$2
N9.++9 O2 %
0!!"2!%
3.2.1. Characteristics of Product Configuration
4 !%
62!2
R'%#%$2N9.++9 O
I'((?2%$'J*
0 2"
%&6
.%4"""%
0 2
2!6%4.A
B"%E2 2
6 2!
%2%
2%
0 D.2
""%2
" 2
!"%4"
8
"AR'%$%$%;2N8 OB%
9+9
?$
6.2 "
2!
2".%
!*
1 +
A
B
AB%4"2
"AB
%9
2.2
"A%I'((?2%;#JB%
2. !I'((?2%;(J*
L 222
! %4
!%
L &2A
B%
L 2
!A"B%&2"
%@
L 4 "
%
9.!"2 AB
!"2 2!2
% 2!2!
"!6 %
.29R;22
!2%4 2
!""2*
2!
*
0 4
%2!
".%
0 &
.%
0 4"!
! %
D!ABR;%;%$%#2N
,O%
D2!. 262
!! %
@2" 2!R'%'%?2N,9.O
72.2
"%
9R$%R9
?;
3.2.2. Product Configuration Processes
+
%2!! 2!!
!AI,#GG(2%
;G<(J2I1 #GG$2%#F#GJ2I'((?J2I-!'((?2%#'$JB*
10 2
%
#10 AB
2!
%
10
!2" "%
! 2!!"%
3.2.2.1. The Global Configuration Process
2
"22!"%2
A!!"!B
. %
D ."I'((?2%
;'J!2
% R$%<2N)9 +O%
Figure 3.5. Global Configuration Process
+9 +
?<
0 % 2!!
"%4!
2!"."%
0 4 "
AB2!
!A"B2
%&
A!
"B%452
!
%
0 4./
. %
257
22.%4
! F*
L 0
7!
%9"2 2
%&
"2 7%
,2%
L 0
"" 7"
AB7AB%
L 0 2
"2! 2 7
2"2
%
@0 4
257
!%
4"2!!
"!* 26
%4!"
%4" "
./%4
" ./I1 #GG$2
%#F#GJ%
E2"2 "%
3.2.2.2. The Configuration Process as a Transformation Process
2 *
2 .2
" %
R$%?2N9 4+O!
"%
F%I,#GG(2%;G<(J2I1 #GG$2%#F#GJ2I'((?J
9R$%R9
??
Figure 3.6. Configuration as a Transformation Process
4%2
A" B
%4 R$%#2N+
,O2""*
% 9"
% 97"
% 9"
% 9.
% &7"
% &
% 9
2 %4
"25%G R$%@2N9 O
! 2!!*
Figure 3.7. Configuration Steps
G2 "2"! 2!
!" ""5!%&2
"%4"22
! %
+9 +
?@
60 &2
%622
7""%
60 4 "
%4
2 "".
!"I:'((;J%4"
"%&2
AR$%$%'%'2N=-OR@%'%'2
N- OB%
80 "2
" %2
"%,2
2
"! %
0 &2
5" %& 2
"" "C
"%
4 2!
"57%
&" 2./
%4 2
%
%
3.2.2.3. The Interactive Configuration Process
0 AB
AB2!"! !
"!2"*
A R$%F2N9 +OB%
2!.
R'%$%<2N, &O%I-!'((?2
%#'$J%
Figure 3.8. Interactive Configuration Process
9R$%R9
?F
4
%4"
%2
. %E2
"" "
2%
46
" .%
&2 % 2
"! *
'0 4"
6" %D "
A(B 2!"
" AB%
10 "2
.2% %2"7
%2 ""
"7%
(@7(8
0 4"2
2R$%'%'%'2N49
+4+O%4!2
" ""
" %
0 & %
46"%02
""%4
2 "6
%
4!"
%&2
5 %
""2
!%62!
! "%
3.3. Product Configurators
2!! !%D!
!.7
" %E62!!!2. %&
. "!""
2!6
%
The Role of Configurators within Product Customization
+ "".I1'(((J%4"
"!"
H H.2"6
I- '((;J%
+9
?G
& R$%G2N+9 >"3,9.O2
".%
!25
%
Figure 3.9. Product Configurator as Key Enabler for Mass Customization
2 5
%2 2
"""
%4 "5
7"262
%422"2"2
" 6I-!'((?J%
82 7
%!.
AR'%$%;%$2N+)4 +9.O2%%I-
!'((G2%';#JB!"%
Origins of Product Configuration Tools
'("2 "4%8
I-!'((?2%$'J*
8$0 #!
%4 2!""
62"
.%
!@10 8 !
%4"5"" %
!%4 "
!3-+"27
"%2"%
! 0 D #GG(2"
2 "!!!2%
3 !"5!
"!9-,!% 2
6"H H6 "
%
9R$%R9
@(
2"6" %6
!2!" "
!!!%0!2!" 9&
3-+%
Definition of Product Configurators
H&!
2!6 2
%4 "
%
76."
HI0#GGF2%#(@J%
2 "!"
A9&B%D"
2"!
.A B
%
4"! %0!2
! 2
7!%D5.
7"! %
3.3.1. Tasks and Requirements
9 6"7%& 2
"
.5%42
2
.%4"2"
" I'((?2%'@J%
0!2" "%
27#(%E2
6
"" "%
D" 2
"%D!
2(*
#0""2 2%%6
%
@70 2.
%D 27
%
50 " 2.2%%6
%##
#(I+'(($2%'?J2I- '((;2%'?J2I'((?2%$$$;2%;G<(J2I-!'((G2%'F'J2I> '(#(2
%';J
##46* 5AB%
" !AB2!6 "
%4"2
6A(B%
4-7
@#
3.3.1.1. Tasks of a Configurator
D2! R$%#(2N49 O
.%D2 !
72!%4
2 I- '(($2%'$=$@J2I'((?2%$$$;=;G<(J2
I> '(#(2%';J%
Figure 3.10. Tasks of a Configurator
Information
4
2 %
42"2"
"!%
"5 2
""" %
Specification / Recommendation
4
2"2 5 %
!2
2
2!" 67%&
"2"" 6
27%
2 5""%4
66"2 22
"%8" ".
%4
72
%
D 27
!*2
9R$%R9
@'
%46"2
!
%4"
%8
5"
"%62"2
2!!"7
%&2H!H62
!A%I- '(($JB%2
" 2
%62!"7
2522
%
Communication
4 2""*.
AR'%$%<%'2
N4 +A+BOB%& C
2.2 "%
2 7
7"7%,2 !
"2 "
" "5 5%4
72!
72.
!%
82 22
%3"26.2!
"2
"%4 2
"%&.2
!!".
2"
!" %
Integration
4"".2 "!
4#'"%E"
7"
22!2"
%25
! "2!
%& 2
! "
23-+"29-,
+,#$" % 2
""7 9&"
! .A% %2$B%
25 !"
!"42"
%
#'&%" "
#$&%-
@$
3.3.1.2. Additional Requirements
D"22
2"
7!%
2"%46"
6.
6 "%4"
! "
2 %
8D27
"% 2 !
%4
7""2!
7%- 2
6!
7""5% 2
" 5! %4
"!"!%
!!!2
" ! 22!%
622 !.
!%87
""!% 6
" %
3.3.2. Features
2
%2" !
"%
! 2!!"""
"!7%
R$%##2N8!,9 "O !
6!%
9R$%R9
@;
Figure 3.11. Overview of the Main Features of a Configuration System
D 2
2%,25
*
@0 32!"
%
L50 9
%
L<0
%
$0 9 %
"2!!2!
!22"2!
%
3.3.2.1. Information
4! 7
2R$%$%#%#2NO%
1%0 4! "5
%2%!
!2" %
"2 ."2
"%""
"%
@<
10 4!"%
222
%&
.%
.".! 2'! $%8!2!
"2. 5
%D!. R$%$%$%;2N9
9O2H.H%
1230 &6!
2!7" %E"
2!
2"
"%& 6
"6%
3.3.2.2. Specification / Recommendation
7
R$%$%#%#2N=-O2"
! %
1230 4
./%0 !2
2! 6 2
27 7
% 2!.
*
L5&0 1"2!
" 6A!2
2622%BA!
B%&22
%2!
.%"
22AR'%#%$%#2
N9.&OB%
L90 2
! A% %2'
$.B%3"2!)
AR'%#%$%#2N9.&OB2
"%4"
2".!%4"5"
"%
& "
%
2! !."
*
L1(7%0 4 ""
""%2
7""2" 7
"%0!2 !2
"!"*
"" !%&
9R$%R9
@?
27!
6%
L@%0 362!2"2
"%4 7
"
%
D!!R$%$%$%;2N9 9
O2H+H%
90 4 "
%82
" A
B%82"
"%3% %2 6"
?(2 "
"!%2
"A"
B%
E"2!"
52
%2 " 2%%
"
%-%
,2"" ""
%42 "2
! 62
%2"*
2 !
!%8"2 ""%
@230 2
" !5"%2
(%8
!%
! """%2"
""5
%4
AB%
4 2A6B
"""Z"%
222
7%4
6 2% %22
7"%
0 2"
22"2! 2
2"
%
-"25
! *""%
2!
! %2"
@@
"A%
I+'((FJB%
4"2" "2
" !%E2"
6 %62
""
22 ++#;"%
0 &
2!=6%
2"%4
6 "
".! %"5
2!!
%
0 2
"6 2
"%4 .
2!" 6
" I- '(($2%<F<GJ%
.2R$%$%$%;2N9 9O2H.H%
230 &
!"
%4"627
%4!
!"%
3.3.2.3. Communication
462"
7R$%$%#%#2N9O%
@0 &.
!%"2
%
2!"
2"%4"
5%7 2
!"
%& 2
!5%
C0 &"
2
%4 "2!
"%8"2
%4 "
"%97"2%422
C7 %4
.!%
230 8"2"
2" %42
"7%2
#;&% %
9R$%R9
@F
""62 "
!%
& 5
6"2!7 %4
"! 2 "
2! !6.
"%
4" "%4
" "
%
3.3.2.4. Integration and Administration
4! .7
R$%$%#%#2N O%
0 8 "
!%
2
%4"2 "7
2!!!52
"%
,2 5" "
2 AI0'((F2%#FJB*
L0 72=%
L10 ! 22 %
L10 1A18,B222
%
L10 +=!%
L10 - 27"%
L$0 42"%
LC02%
L$0 %
3"722! 2!
" %4
7
%
$ 230 4 !
" ""
5"%02 "
"!
"2*
L 0 9!=229-,"
22%
L10 3-+2++2+,2 2%
& "22"
.%2!"
"!2 [,:#<%E2!"
!"62I> '(#(2
%$<J*
#<&%<9
@G
L 3&94A3 &294B2
L 4-&EA6 B2
L [,:A9[,: B2
L 691:A[,:91:"B%
82(30 ,"
%1" !
A&+B2"
""2!".%4
"
2! %
2&(30 1"6
! 2"
A+B!"%4 +
" 2!!2"
2%6 2 !
! "*
L$0 4 %
L1$( #?($#@(0 4
%
L 8$0 4! .%
L!@1(110 4 "
%
L @0 4%
L60 A8B"
!"2% %2
2%
8230
22 2 "5
"%4!
2 %
"5!2
""2
+%
3.3.2.5. Other Features
1"2"5""
2%42
! *
:230 4 2
&!
C %82 C
2!"7%82
C6 "
5%&2
77" %
230 .2
!%1"
#?&% %"
#@&%- %"
9R$%R9
F(
2 !"
7"%4"2
" %
230 - 52
""!
""%26 =
%8 2!
"!%4""
2 !% 2 2
2% %2
"%
9 52"!%
62""
"22!
C "%
3.3.2.6. Development
"2" 2
%D!!
*
$230 ""
.HH!22
7%
22
2 2"
5%
#230 &
! !2""
%& "72!
! "%
62 "%
7 C2
56"%
46 ""
%&A'$B2
"527" %
-"2 ! 2!!
C"6%8
2.2
%42
"%8!29R;22
"6"%
3.3.3. Categorization
1! 2 2!! 2
"" %D
6""2 .
2"2%42
"
%
9 .
F#
" 5"! "!
2 "%2
.!". "%
2"626 .2#F%
2)#G""%
D! . "2
"62%D
. 6""
%4 6"! R$%#'2N, 169 O%
2! *
8"0 96
"%,26 !
""%
0 9 .
"!%4."5
%
0 )! "
"2 .5 %
0 9 "
"%2
%
25*
L 0 9.
%
L0 9
" %
L 0 "
"%
L1 0
.%
0 +
%
D!!2
!%
#FI1'((;2%'?$(J2 I:'((?2%;G<'J2I'((?2% <#<@J2I-!'((?2%$($$J2I-
'(#(2%@<F(J2I> '(#(2%$G?(J%
#G4 6 \!"2!
I\!"#G??J%
9R$%R9
F'
Figure 3.12. Morphological Box of Configurators
9 .
F$
3.3.3.1. Application Context
10 257!"C
! ""*
**%&
2.2""
!" %4
"" "
"2R$%$%$%$2N, 9O%
<0 &"" "
%.3:3/2
!! %4.
"%2
6.3:/26
"! 257
! %
0 :!2 5 *
5""7""
%02"%
&")2""2!!"
" %36"
.%/2252
" !!!%2
A" B2
!2"A!"B2!
"7"%H
HR$%$%$%;2N9 9O!
%
#0 4"!25!5
%%27"2
7"2 "2
""%&62"'(A% %27
2BA% %2!2
!%!B65!%0!2
A% %26 5"B
A% %26B"6'#%
"0 4 .)%
D 22"
%
& A""H HH7
HB %4""
2"5"%
"%
4" 9-,"%
9 9&"
%4"5" 2
'( " 2 *==%!% =!
=3EV8VG';#]3EV8VG';###(V)%9$%&;.VV 2,"#F2'(#'%
'# " 2
*==!% %=!=='#G<;<@;="^+^^^^
^96%PW#2,"#F2'(#'%
9R$%R9
F;
!%&"
'! %
9 3-+"!2++"2
%4"!
!
"%
2"2
62"%
0 25 .
6%+"2 "
%
& "5
A%R$%$%'%$2N9
OB%47"!
" 2"2 %D
!" 2
"%4"!
"7 "225
!%
82 ! ""
%
C0 62
AR'%$%$%;2N8 OB"
".2"
%4
"5"
%42
%" "6
" %97"2
%
"2 3-"
"27!%
3.3.3.2. System Environment
D2
"62%
0 &"2"%9
" ./A% %29=B
%E!"2"5"
1'9" %0!2"
!2!*
L 62"$"A% %29&
! ' B2
L !A% %2.
B2
L A% %2 2"
2%B%
9 .
F<
"26%4
".
%
&"".%D"
2 %42
!7%&604,:''
! %
2"."2
AB%2A""B
!! A"B "
!%36"04,:<'$H6H
7&2/&=D
I+"'(#(J%
22 !
%4"""
!7 %
0 & "5" "
2AB
%42 2""
%D7 "7
A"B22
".AB%4"."
=7A"2% %2&2/&=D
B""
A"B%
0 & "
% "2
"%!!26%
& "7"2
!62 !"A
B2%8!2
"2"%62!
!3-+"2!
%
46 2!
%2" "
" 5&+=+
%" 2
"%97"22 2
"2%% % R$%#$2
N 9 "O
%
''&%=" 69
'$,"*04,:/2. 04,:
<%
9R$%R9
F?
Figure 3.13. Different Integration Scenarios for Configuration Systems
0 4 ! 5
."%& R$%#;2
N :9 "O2! *
L 2
L 2
L %
72 "2 "
"%4 """!
62% %2 "%
"56%
2 ""
2! "
%4"22" A"B!
%
"2 56 2!
%4 2
"6"!2 A&+B
A+B%&!&+"
%2
6%&+2""
"%62"
2! +%4! "
==%+2 "
%
9 .
F@
Figure 3.14. Integration Levels of Configuration Systems
#0 4. 5"2
5 2! "%
4 "" 52
%25
020%4".2
!22!!
"2!"*"
" "%
3.3.3.3. Modeling Capabilities
E6!!27"
%
0 252
! 5
%R'%#%$%#2N9.&O!!
.%42)20
22222)
)%D
7".
"%4""2 "!
%
:0 1" 25!
"!7%D "
22
2!%8!2
%
10 & " 2
%4"2! "
" 2 ""%,2
!2! 2% %2
9R$%R9
FF
!" %
3"
L 2
L 2
L
%
7 "!
7! "%8
"! %&2"HH
!"7%
962!! C!7
! "%4!"2
"5! %E2!
222
%
42!
%02
! %42
! "*!
!2!
!%0!2
"%
3.3.3.4. Configuration Characteristics
46 " 5
%
Configuration Approach
2 .%
%
0 2
L 2
L 2
L 6%
R$%#<2N)&O"%
9 .
FG
Figure 3.15. General Specification Approaches
2 . 5
2!!"%4"
5"22
2% 2!
!7%02"
! !"%
22
5%42
% 25"
2"%4!
72!C"!
! * 27
%
&2 6
%2 " 7%4
7" 2!
C"!"%
0 4
% ".2 R'%G2
N4",.+ OR'%$%$%$2N,"O2!
! "*
L0 " .
2 6
".%62
" %
L"0 (
2AR'%#%#2N9OB
"%&66
"%5 ';%
L80 +
2%1"
';*==!!!%"%I*==!!!%"%=J2,"'(2'(#'%
9R$%R9
G(
2%E2
6."%
L$0 86 %
!"%4
%
R$%#?2N-1!9 4"9 O!
%-
R$%#2N1,,)+, O
%
Figure 3.16. Relationship Between Configuration Type and Configuration Decisions
Interaction characteristics
0 2
"%
0 4./2!!"
26
!!"* %
32 " !
"%& 27
9 .
G#
%4 "2
%4" %
42 %02 !
!! *!
""72
"""%
10& %
" AI'((?2%<'JB%4
"7! %*
L1&"0 46 %
0""
6". "%
L0 45"
5%222
5"7%4
"AR$%#%#2
N9*OB%
LC0 4 5
%62"72!
""
"%4"%
L$0
2%2"
""%
L 0 4 2
"%27
!%
L80 & "C
"%4!
7%
$0 "" 2
" "" %4
5% 6
"%
&)77A(
"B
%& 2
%, %
2" .%07
!7 %
".!26%"
!6%&2
6%
&2 "
5.! %4"7"
2"!%0!2
%&62"
!6%
2 " "%
9R$%R9
G'
Configuration procedure
4A B
."%
0 4 ""
*! !*
!5" %4
2 %
82"
!%3"2 !"
%"
AR'%$%$%$2N,"OB2! !
""
%62" 2!
"!26%
,2 !)
""""
'<% !6 7
AR$%$%$%$2N, 9O2H+
HB%
0 2
"'?%,"2
2!!"
"!6 %2
2 !
25%
6 & 0 &
5%D"
5 2"
. 2!22 %
1"25! !
!5%&
"25 "
%D""
"%4"2 " 2
"%
0!22"="
*
LC&0 2
!%&"
AHH!B%9"
"%4"22
%
L:&0 4
"5" %D"
% 252"
'< "2 "
:I:'((?J%
'?I> '(#(J2 H3 H2!"
%
9 .
G$
""2
%3"25" "
%26
" %
&"262""
5%42"""AR$%#%$2N9
*-OB"%9
! 6*A!{0, 1, 2, 3, 4,
5, 6}2""2A < 4%
4256"!"!"
C6%& "2
"2!"7
A 07"0!
%0!2"6"2
"62!%9
""%
L5&0 4!6*
0! A5{1,
2, 3} 2!
"" "%2
2 ! "
72!!"!"5%
90 " 2
5%D"
!"2")2
2%!2
%&
%D! A%
I> '(#(JB*
L'(0 4 %5
"!%
L(230 4 "2
%"
"22
" %4"25"
2%
L@230 42
" 5"""
2% %2 %
L 230 8"2 "
"22"%4!"7"
"%
&)2"2
%2"
%
0 & 2
%&
%+"
7%
9R$%R9
G;
-! "! !
*"2 %1"
2!5HH
%"2" "2
!
2%
!"""
%522
7A6"
B%4!""
%&"2!2 6""
*72
" 27"
A2;R$%$%$%;2N9
9O2H+HB%
72
! AB25AB%
&
*%8
)2% %2"6
2)2% %2
" %
27
%4" 6
%4C%4
2% %22!
%4C"2
!!"!AI- '(#(JB%
Presentation
9 ""!"%42! 2
%
0 &"R$%$%'%'2N=-
O2 %
9 )02!
!" AH+"H
!B%&"2 "
AH.H!B%9"2 26
%
90 9 7"%
%4"5"
%422". %
4 " "2
.2"""%
!2!*
L'230 4"!
5"%
L:230 "!!
2% %2 C
9 .
G<
% C
%
L!"230 !
C%4!"2"
%
-!I- '(($2%
<G?(J*
L$230 4
" " .
%45" 2"
"%
L@2))30 4
""2 %D
62"
6"2 %
I- '(($2%<G?(J*
L1(0 4.
2 % 2
%8"2"
%. 7"2
! %4"7!%
L 0 ,
! %D 7
"2"22
%1"."2.""
!7%
L@0 2
"" %
2!6"
%82 6"!"
."%8
27 5 "
" %
L+$(0 46.!
6"%4
$
"%D!!'@!
$72!"
"[$'F%2$
7!*"
.2" !
52.%
"2 .""%&
!"!2 .
%&.!"
'@D!!" !%
'F*==%!% =!=[$2,"#;2'(#'%
9R$%R9
G?
2
!%
10 & 2"
2A%I+
'((F2%##JB%25!
62"
%
2
2% %2!6
2"C5%97"2
" 2"5
%42
!"6%
2)76%02!
!*"%2
"25
52"%2!
!"2 22
5%2"
"22!!"
!"67%2
"! %
3.3.3.5. Implementation Aspects
.2!!
2 "%
0 2
A%I'((?2%<;JB*
L 0 4 2
%+! "!
%
L80 4
2% %23-+!%4!
52! " !
%
L%0 4 !%
4""" " "
2"A% %22
H"H!B%2!""
"H6H6
.%
L@0 &6 "2% %2"2
%
L1&%0
!2! "
!%& "
! 22 2
2 "%
9 .
G@
C0 )2
" %&
2 "%
2* "
"%
80 "2 ! "
" % !
2!267
I'((?2%<;<@J%
D7 22"
%2
! 2%%
! " I'((?2%<;J
AI#GGFJB*
L$0 4
2!5
"%
2! I- '(($2
%F(F#J%
L@0 - AH-H
R$%#%$2N9*-OB!
%46!
"6%& "
"5
%,
I- '(($2%@@@FJ%
L 0 4 " 2
%
! %&
%
"2!2
)2%%
! AR$%#2N+,OB*
L$0 9
"%D2!
2!6
"%" I- '(($2%@GJ%
L@0 9
%02"2
% 2("
%4" %
4 25%
L 0 4
! 2 2 ! 2
! %9
!2%%2""
%4"2"
%4
2I-
'(($2%@FJ%
9R$%R9
GF
4 12 13*
! 2
%
L 0 & 2
!2
22% 22
"%427"
7%9
"! 2!
%
L6;0 2
C%DC
2!"2
.=.%D
A"B2C2%%2%
2C%
9 %
72
7*
LB%0 ! 2!)
2 !%
4 "
! %6"!"7
2" %,
7 "
I- '(($2%F(J%
L470 &272
" %2 "2
7%
4! .%:
R@%#%'2N9.O!!
9R;2 6
""%0!2 "
2!5
"%
3.3.4. Benefits
R'%$%;2N3&O2!"
. %02!!" 2
"" %
! A%
I'((?2%;$;;JB*
Supplier Perspective
0
L 6" "
%
"
GG
L -" .%
L ! " !
" %
L ".7
2 "!
7"%
L ," 6%
10
L ! 2
7!
%
L 37"
2"
%
L !%
L !. !"%
L -7""
!%
0
L - A%%2
! B" " %
L - A%%722
6 B%
Customer Perspective
0
L &2.%
L %
L "AH"!HB"AH"HB%
L - %
L ,2! 2
%
4 "!
%3"2! "5
7"2A-8B
"%
3.4. Summary
2!.*!
! 2
"%
& !22!2
!%+"
AR'%$%$%'2N+&OB! "%
4"22
%+"6 2
"AR'%#%$%#2N9.&
OB%2" %
"22!"6
9R$%R9
#((
2
%1!".6
A2R;%;2N, 9OB%
E62!2!
%D.
*./%4.!
!.2"
.AR;%;%$%#2N,OB%42
! " A
B%4 !
2
%4" %
2!5
5!%
4!%D6
!.2
7
. %,2!6"
"%"2
%
4!%"
" %9R;2
2
"%
#(#
4
Methodology and Conceptualization
2!!.
*%D !2"!"
. 7"2 2 "
.%
&R#%'2N,O !2
""! *
#% 4.
%
'% 4.%2
6
D2!2C9
R<2 !"2!89
" %9R?2
#$!!.2
! %
:5 !689 5%
4.1. The OpenConfigurator Methodology
& 289
"%D""2!
" %&"2""
7!2"
! %472
"2
%
89 22
2
9R;%R, "9.
#('
6 6"%4"2 ""26
%! 2!!."
6 6%
4.1.1. Main Characteristics
4"289 5
%"289 5 *
L 2
L C2
L 2
L 2
L /%
D5"6!%
0 89 %42
%4
!5 !
5"%"2
" ! 22
"5 %4
! "2"2 ""
" "%,2
"! " 2
"! ."A,B "%
6;0 ,"289 5
2%4"2!
7"
! AR'%$%$%'2N+&OB%D!
.2!6"
%2
"%"2C
"" "22
A88&BC A88+BC A88+B2
%:2C
"%
C0 &89 5
5%4!
"%2 "!
%8289 "
2!
%422
89 !2""
2!" 2!
6 "2%4
2"
"2
HH!" %
$0 4.!5"
2 %D
CA%%/
2!B2! !
,9
#($
A%%/B%4!
!/ !!"/ "%
2!
2."%02!
5"A% %2"
!6B%4
6%
E0 & "72!
",%42/
%2/ 2C "
*2
!22
" !/%4 2
!2"" 2 2
! "!HH%32
89 5!6 2
/ A% %2/12/+&212%B
/ !!7"%
The Fundamental Idea of OpenConfigurator
4 2*
L2E32
L2;3
7"2
L AR$%'%'%'2N49 +
4+OB2E3%
4. " R;%#2N48
9 &O%
Figure 4.1. The Fundamental Idea behind the OpenConfigurator Approach
489 !2. %
82!2%02
A/1B %
D5 %
9R;%R, "9.
#(;
4.1.2. Configurator Development
H H "2"
2!5 ! "2 R;%'2
N8!89 , "O%D!"6
!%62!5!.
!%
Figure 4.2. Overview of OpenConfigurator Methodology
& ""2 "
2 %"
" "%
46%
4""62!
! %"" 2
2"!2%% %D
!2 2
" " %89 5C
2! 6 2,:!
% "
7 ,:89:
6AI '(((JB%4 ,:
. /27
9
#(<
"89 !#%&.
!'%
"2
/! /2"
89 !%4
%2
2 " /
! A3B$%+!
3;" %4
6"" /?5
"<%" !
?%
4 " A B2
2" /2
%
42 /A/&-B"
2!" %
4!"/&-
(%4"
"2
A+B%
42 5
"%2(
A%%!"B %&
7 222
%4&+@
9R?2#$2
2! " +%4
"! !!
23-+29&+,"%&! 2
%
"2
%02"2 /CA,22
+8/8B
&+%4!"C!"/ " +8
/82/&[1F[,: 2/&[DG!"/+&#(
#E2",:/2
!" %0!2
"!%
'E*89 !"56
!%
$E*! .%& 2
89 H H"" %
;*==!!!%% =2/'#2'(#'%
<*==%%=C=?=== ==6%2/'#2'(#'%
?EC!%
@*==!!!%%===2/'#2'(#'%
F&% , ! <,: 3 2 *==%!% =!
=/V&VV[,:V1 2/'#2'(#'%
G&%,!+<,:>%2*==%!% =!=/V&+VV[,:VDV2
/'#2'(#'%
9R;%R, "9.
#(?
CAC!B%4
89
!6%
&"2 " %42
/ A6
B7 %4 !
-X##22 "6
""%
&252 "2
7%E2 2
2"!%
6!2!2!! 7
2!6
%
4.1.3. Other Approaches to Configuration
0 .25!
2"
"% R;%$2N8!8, O
! 2CC%
Figure 4.3. Overview of Other Methodologies
#(&%,!+2*==%!% =!=/V+V&+2/'#2
'(#'%
##&%-58?2*==%!% =!=-X2& #2'(#'%
& 89
#(@
36 "2
" %9A%I-
'(($JB!522
2!"
%47 27
""%+"2
6"2
72"7"2
!%
&"C22"
"%1 *".,:=89:#'
! %42"
AI '(((JB%
0!22
&%4
2%4""
2 2
"2"2C
2"%E2
! 22
HH%4 5
!A% %2+ 22%B!
%4"2!
!2 6%
"2(
2 " C%4
2A% %2/+ 2/+B2!
". ! %4
!2!!
!%
4.1.4. Advantages of OpenConfigurator
2!
"2! *
L " 2
L !
L 2
4"*
L "
L
L 26
L 6"2 ""
2! *
L ". "2!2C
L "/2
#'&%; 9 =C9 %
9R;%R, "9.
#(F
L " !
/
L "62 6
L 6"2"""
4 2 *
L 2
L 7"".2
"
L A-8B""
"
0 .89 5 "2
!2
!!!!
.%
4.2. Modeling Approach
4 2#$%
.R$%$%$%<2N&O2
.!*
(0 4 "
2%4 "
", "
/1#;%D2.
"%
4C!
AR'%$%$%'2N+&OB89 7
%
0! "2!
R;%'%'2N+,/O%
(0 "2/
A"!"H!"HB%4
2"2!!
R$%#2N+,O2"6%
02.
"AB.AB%4
6R$%#2N+,O
7""%2"
2AR$%'%'%'2N49 +4+O
B%
R;%$2N4)9 ,O!!6
6"%R;%$%'2N,, O!2!/
HH %
#$8 ""! %2! ,:
7 ! #(" I '(((J%
#;*==%!% =!=/12& #2'(#'%
8C8+,
#(G
0 8.!
AR$%#%$2N9*-OB6
"%
DR;%'%$2N+ ,!/&O"!2!
A B6"2R;%;%<2N9
, O!!"%
& "67AR$%$%$%<2N
&OB2! %.
R@%#%'2N9.O9R@2%%
1 " 89
!2! 6 %
4.2.1. Object-Oriented Product Modeling
&R'%$%$%'2N+&O2C
"!%
2! !C !
AR$%#2N1,,)+, OB
!2 !7 5
"*
Table 4.1. Mapping between Object-oriented
Concepts and Product Modeling Concepts
6;6 1
9 +="
).=. HH=HH
& = H9H=HH
8C +=2
AB &
,"./ &
, 9
4"./ 9
0D2%&
"%
&0 . 20
62!!6
%3% %233.
3$3=3."3
%
8&0 !"
%23
242=2>212%
6;0 &2227%
%&C6
!25%
5 2 30 2""2"
2!!%4"
9R;%R, "9.
##(
C2"
%2"2
!C!!color%
0 &"2% %22 2 %
4"2 %42
"5AHHR$%#%'2
N&*99OB%0!26
"2 ""%4
"%
0C%
!"2".A
R$%#%'2N&969 OB%3% %2
""%
# 0 2! !C
"2"5"*"2
"%2"byte2
-/+255 24711%42
A"B"5"%
R;%;2N368C8+,O!6#<
3%D
R?%#%$2N41,O2!56!%
Figure 4.4. Example Object-Oriented Product Domain Model
"2!R$%#2N1,,
)+, O2C /
C"7 "%0!2
""
2!!"!!76%&
"5"2R;%'%$2N+ ,!/&O289
. %
#<D,: !%
+,/
###
4.2.2. Product Models in Java
0 C2!
!! / #?
%62/1#@ %,
"2.2
%4!"!"#F%4!
2 /12!/
6#G*
Example 4.1. Example JavaBean Domain Model
public abstract class Bike {
// Fields
private Frame frame;
private Fork fork;
private Wheels wheels;
private Collection<Equipment> equipments;
// Methods
public int weight() {
// ...
return calculatedWeight;
}
// Accessors
public Frame getFrame() {
return frame;
}
public void setFrame(Frame frame) {
this.frame = frame;
}
...
}
public class MountainBike extends Bike { ... }
public class CityBike extends Bike { ... }
public class Frame {
private int size;
private Color color;
// Accessors
...
}
public class Fork { ... }
public class Wheels { ... }
public class Equipment { ... }
& " 2 !*
2!/1"%
#?*==!!!%C%=2,"';2'(#'%
#@*==%!% =!=/V12& #2'(#'%
#FE*89 "."2
7 java.io.Serializable%& 2
A"B%
#GSerializable"%
9R;%R, "9.
##'
& 289 2 6
"/% 2/
2 *
#0 /5""%1
%D . )
"!2" "!A/5
!"B%&2"2
%:!2
"%&"2""""
89 !%
1(0 2/
"Aboolean2byte2int2double2%B2"AString2Integer2
B"A "!B%
8(0 &"2"A% %2
String[]B"A% %2Collection<String>B%4!"2
% !"A% %2EquipmentB2
Collection<Equipment> 2
%,2"2byte[]InputStream2
! " %
0 . 2 /%
D2"!%6
2"double getWeight()!
%
- 6"289 !
%42! 2
6""!%2
!/
%4"!
%D!
6%
4.2.3. Providing Meta-Data with Java Annotations
&289 2 ! !
2 2%2
"!* /'(%
2/2"
!/ 2"
" "%
/"
2 "222%4"!
!%2"
2 "'#%4!
236R;%'2N36"& O2!
Description2"2
!%,26
Frame*
'(*==%%=C==C=C88=%2& #2'(#'%
'#4 @Retention(RetentionPolicy)%6
!%
+ ,!/&
##$
Example 4.2. Exemplary Annotation Definition and Usage
@Retention(RUNTIME)
@Target({ TYPE, METHOD, FIELD })
public static @interface Description
{
String value() default "";
}
@Description(value = "The base element of a bike")
public class Frame
{
...
}
D7" !
/2 3/1''2/+&'$1';2! 2
%
Annotation Usage within the OpenConfigurator Methodology
D 89 !2 " % 2 "
289 2!H H
!"%42!
R;%;2N, 9O2!5"
!6
%
4 ! "2!!
! %"2*
0 &/
2!!R;%$%#2N3
)9 ,,,O%4!"2% %2
2
%4!
2%02
!2"2 % R;%<2
N &,,),,O
%
''&%# ,32 *==C% =/="==C''(=6%2
,"';2'(#'%
'$&%,!+2*==C% =/="==C$#@=6%2
,"';2'(#'%
';*==C% =/="==C$($=6%2,"';2'(#'%
9R;%R, "9.
##;
Figure 4.5. Using Annotations to Map Domains Models to the Generic Meta Model
$0 D2C
7 27 A
R;%'%#2N8C8+, OB%4!"89
* %1" 2
HH226
%
R;%?2N &O2!
!!
5*
Figure 4.6. Using Annotations for Domain Definition
0 :!2!
2"2 C %
36R;%$2N &9O%
+ ,!/&
##<
Example 4.3. Using Annotations to Define Constraints
public class Bike {
...
@Size(max=10)
private Set<Equipment> equipments;
...
}
27"76#(%4
!"/-'<$($'?22
./%
289 !1!
26 2 %
C0 D2
"AR;%$%$2NOB'@%62
""2 6
62!%4 R;%@2N
&, O%
D 2 "6!
2! *
L 0 R ;%#%'2 N9 O2 ! 6
289 %
!-X22/
H H%
52"
%
02 2
%
L$(0 AB
2"2!.
%42"
"2""
222! %
42 !" " 2!!
%
'<,%87
'?*==C% =/="==C$($=6%2,"';2'(#'
'@E"%
9R;%R, "9.
##?
Figure 4.7. Using Annotations for Declarative User Interface Mapping
4"62
!R;%;2N, 9O%1"2
%D2
!%
4.289 !6
% 2
2%D!6
! !
6%
4.3. The Generic Configuration Model
42!
2%
"22HH
2
%4" R;%F2N4)9
,H1H9 +O%
Figure 4.8. The Generic Configuration Model
as "Backbone" of the Configuration Process
4)9 ,
##@
4 R$%#2
N+,O%3"222
26!ABAH
HB%&
!
%42!!R;%$%#2N3
)9 ,,,O%!CR;%$%$2
NO%
Representations of Configurable Products
89 2 %,
2!! 2!
%
:0 2! %
L#0 &R;%#%#2N489 O2
!2 /%&/
2"5 %02
! %
L0 82 /C%&
2/"A B/CA
B%42
"%
& 2589 !/2
.2 %
2!"
" %
@&%0 "2 *
L:%0 4 !".89
* "
%42!!7
"AR;%'2N, &OB%
L0 &7!%6
2 *
2
%4!"A
R;%#%'2N9 OB%
4. 2
%8 !2
A! H HB
%
&289 "". !!
'F%
Relationships between the Different Levels and Representations
4! R;%G2N-
)9 ,-O%
'FE*""H!"".H*
HH 2%
9R;%R, "9.
##F
Figure 4.9. Role of the Generic Configuration Model and its Relationships'G
4 2
2!!2 A"6B
!6"%822
%
42 /
AR;%#%'2N9 OB2"
❶%42
2!
❷%" %
D
)%
2
%42"2
'GE ""*PartDescriptorPartAR;%$%#2
N3)9 ,,,OBProduct-
Descriptor566"M2 !%
3)9 ,,,
##G
❸%4AB%
6"%
0!22"6"""2
AB❹%42
" /122 !❺%
&"22 CHH
❻%,"2
!"2!2%
E62!56 "
%
4.3.1. Elements of the Generic Configuration Model and
Meta Model
! 2!!
"% R;%#(2N,:9 )9
,-O,:%
Figure 4.10. UML Class Diagram of the Generic
Configuration Model and Related Descriptors
0 4Configuration!2
%! A !Bvalue%&
rootComponent%
& $0 4Component"
"% %&
9R;%R, "9.
#'(
A"B "Xvalue2
!% " Attribute
Part2 "%4"
"type%2"
FacetA!B%
&6""X%&"
""" 2
" %4". "%
8&8$0 - 26"
C%82"
""%4"%
&AttributeDescriptor2!
/52%DdeclaringType /
"2!declaringMember6%4
2declaringMemberA B%"5value-
TypeA/5!B"
"22!"5
collection%52
"2readOnly%
1&1$0 &Part6" C%4
2 !
"%Part22
Component2 "2 "
" %45" type2
ABvalue%
2PartDescriptor
"%47AttributeDescriptor
AB%
5&5$0 4!
7 2%&Facet
%4!"2
2 "$"2"Component2AttributePart%&"
22!
%36*
L10 &! %
L 0 + %
L$0 "%&! 5
5%
L9&0 3%
LC0 %
"72FacetDescriptor2!
"%D!R;%$%$2
NO%
4.3.2. Model Mapping
D C7/
R;%'%#2N8C8+, OR;%'%'2N+,
#'#
/O%2R;%$%#2N3)9 ,
,,O2! 2!""
%D5 "2 !
%2!!!C
%
24R;%'2N, !/9)9
,O. *
Table 4.2. Mapping between the Java Concepts and the Generic Configuration Model
E<
$
# 8
$
9A/
"B
" @Component Component 1"2
/
A B
%
+"
A2
=
B
^!2
String2Enum2
InputStreamM
"
@Attribute Attribute &)
/1
A,:
B
!
%
+"
A2
=
B
ObjectA"
B
"
@Part Part &)
/1
A
,: B%
%%
"26
2
A B%
"2 "!
5%D"%2"
)%
4 !)2!"
.AB% 2
/ "%
4.2!
%D!
6"R;%;2N, 9O%
4.3.3. Facets
489 %&
!!R<%'%<2N+ 9O2"7
6"6"!%D
"/12
!%4"2
$( %4" "
$(*==%!% =!=V2,"$(2'(#'%
9R;%R, "9.
#''
% R;%##2N &9O
%
Figure 4.11. Usaging Annotation to Control Facets
2!2
=%R'%$%$%'2N+&O!
7%
0!2"!289 ."!
%9"!! *
10 362%
4!2
%22.!"A
R$%$%'%#2NOB%
0 + "
" %62
7"2
%"2!%
$0 &!%22
%,2
"
2!"262+,"2/+&
/9-$#"%
90 3%4
" %6
2!1I/-$($'((GJ
2!9+
&+$' AR@%'%#2N9+=9 OB%
$#&%,8"2 2"
'%("/-'F$2*==C% ==C=PW'F$2,"$(2'(#'%
$'*==C% ==C=PW$$#2,"$(2'(#'%
, 9
#'$
C $$0+ " .%
4 $;2!!
%62"2% %2H!
H%H H2%4.
"! "A% %2D4$</$?!"B"
89 !2
!%
4"2%02$"
"%2/+&A
I/-$#@'((G2%#@GJB
AR<%;2N+ *36 89 OB%
4.4. Modeling Concepts
E!! !7
"25 %
2 2 7
9R$2%"2R$%#2N+,O
2!R$%'2N+
9 O. "%
2!!6 .%
+"2! !!
6%,2!56"!"
6 6%
4!*
0 R;%;%#2N, O
2!"E<
%,22 2
26%
0 2"52!/
"89 !"%,2"
2! 2
2"!"%
10 E62R;%;%'2N+, O2!!
%A!
R'%$%$%'2N+&OB% 62
!!A
R;%$%$2NOB%
0 9 CR;%;%$2
N9 , O%4*
L !AB2"/2
.2
L !
2 !.
AR'%#%$%#2N9.&OB%D
$$E"%
$;&%;"
$<&%%> 2*==!!!%% =!=2,"$(2'(#'%
$?&%,%42*==!!!%%=!=C=C=C#$GF?G%2
,"$(2'(#'%
9R;%R, "9.
#';
2 !2
" %
&62 !
A
R;%$%$2NOB%
$0 0 2!.!"
2 !2
%423
CR;%;%;2N, O%42!
%
4"A-R;%$%$2
NOB%
0 "2R;%;%<2N9, O2!
..%D
&6R&22
!%
2!
2 A
R;%$%$2NOB%
27 !2
%
:5 ! .%
4.4.1. Structure Modeling
1"2R;%$%'2N,, O"!2!
! "%42=
6"289 ! *
Table 4.3. Structure Modeling Annotations
8 $
@Component " ."!
%
@Attribute " "!%
@Part " %
@Ignore " "!%
D2 "AR$%#2N+
,OB%! 2!!%
4.4.1.1. Components
2%/
"AR;%$%'2N,, OB%
1" /!@Component2
./%& "!5&+%
"/2/1$@%36"
$@E 89 ! " 5 7
java.io.Serializable/12 %
,
#'<
!@Component!!"
6 %
&6 @Component! 36R;%;2N
@Component&O%
Example 4.4. Usage of the @Component Annotation
@Component
public class Product {
private Assembly assembly;
...
}
@Component
public class Assembly { ... }
Runtime Representation
"2 "
ComponentDescriptor2! 6%D
2 "Component
C% R;%#'2N--9O
,:C %
Figure 4.12. Runtime Representation of Components
2! "
" CA/1B2!
%
Responsibilities
4! *
L "2
L 5" "" A!B2
L 52 ! *
Table 4.4. Component State Variables
9 $
abstract 2!5
"%
instantiated 2! "
"%
9R;%R, "9.
#'?
9 $
specified 2!6"
"%
L M 2
L *.
$F
L . *!
! *
Table 4.5. Component Events
! $
Change 4 "
A% %2 2" 2%%%B%
ValueInstantiation
"%
ValueChange 4 !
A% %2= B%
TypeChange -!" 5"
A!7
CB%
Reset !%
L * ComponentDescriptor
5"" %
""289
"!"A "B2
! """%4"2
!2 52%E2
! A!B
"$G%R;%<%'2N369 +O2!! 6
" %
4.4.1.2. Attributes
4""%/
2/1"22
=%
& AB AB!
@Attribute26"";(%1"2
"2!! "A "B
*
Lbyte2short2int2long2float2double2boolean2charC!2String2
BigDecimal
$F*==%!% =!=V2/<2'(#'%
$G89 2! "
" %
;(E 2""
""%42"289 .
2 "
%
,
#'@
L " 2 % %2 int[]2 byte[]
Collection<String>
LInputStream2Enum
&" AB"A
B%
4! 236R;%<2N @Attribute&O2!
%
Example 4.5. Usage of the @Attribute Annotation
public class Assembly {
// implicit, singular String attribute, field access
private String stringAttribute;
// explicit, singular Integer attribute, field access
@Attribute
private Integer intAttribute;
// explicit, plural String attribute, method access
@Attribute
public Collection<String> getMultiValueAttribute() { ... }
...
}
Runtime Representation
&2 Attribut-
eDescriptor2%%SingularAttributeDescriptorPluralAttributeDescriptor2
5"%4 "
Attribute2%%SingularAttributePluralAttribute% R;%#$2N--
&O%
Figure 4.13. Runtime Representation of Attributes
Responsibilities
4Attribute" "
" "%4Attribute
.!*
L ! "
9R;%R, "9.
#'F
L 52 ! *
Table 4.6. Attribute State Variables
9 $
instantiated 2! 5
"%
specified 2!6"
%
L *
L . * !
;#*
Table 4.7. Attribute Events
! $
Change 4 " %
L ;'* AttributeDescriptor
5"%
4.4.1.3. Parts
96" %:2
/1"22 =
%
1"2ObjectA62
R;%;%#%'2N&OB%4"6"
@Part%2 AB
AB%36!36R;%?2N
@Part&O%
Example 4.6. Usage of the @Part Annotation
public class Assembly {
// implicit, singular part, field access
private SubAssembly part;
// explicit, singular part, field access
@Part
private SubAssembly anotherPart;
// explicit, plural part, method access
@Part
public Collection<SubAssembly> getMultiComponentPart() { ... }
...
}
public class SubAssembly { ... }
Runtime Representation
& 2 "PartDescriptor2
%%SingularPartDescriptorPluralPartDescriptor%422
;#&"%
;'E"!"6%36
!%
,
#'G
+2%%SingularPartPluralPart%2!
" /152/1"5
%82"
!!22
%
R;%#;2N--+O!,:C
%E,: 2"
2"%
Figure 4.14. Runtime Representation of Parts
Responsibilities
4Part !!
% AB%4
Part.!*
L
L "" AR;%;%#%#2N9OB
L 52 ! *
Table 4.8. Part State Variables
9 $
instantiated 2!2
"2"%
9R;%R, "9.
#$(
9 $
specified 2!6"
"5
%
L * !
AB
L . * !
*
Table 4.9. Part Events
! $
Change 4 "
A% %2 2"
2%%%B%
ValueChange 4 !
A% %2= B%
L ;$*PartDescriptor
5"
0 26!
!2!!2
%
4.4.2. Product Modeling
D.2!"
"%4! *
Table 4.10. Product Modeling Concepts
8 $
@Product "A""B
%
@Product.Name 5%
@Product.Description ,%
@Product.Attribute %
HH2
%4"
22 %
4@Product.Attribute
! *
LlabelAB*String
LlevelAB*int"
%D *
LUNDEFINEDA0B
;$E"%4" 8
9 %
+,
#$#
8 $
LIDENTIFICATIONA1B
LSTANDARDA2B
LDETAILA4B
LSPECIALA8B
4 %
@Product.Asset,%4
"byte[]java.io.InputStream%
4@Product.Asset
! *
LnameAB* %
89 !
*
LPRIMARY
LPRIMARY_THUMBNAIL
LSECONDARY
LSECONDARY_THUMBNAIL
47722
2% %2" %4
%
@Product.Price 5%
4"""2!2
BigDecimal
%
+ . "%D!
.%3% %2!5!"
%
4 5 6 info.openconfigurator.products.annotation.Product.Asset.
"%4&+7"%
E"@Product.Price289 5""
""%97"2!5 2
"%D! %
36R;%@2N @Product&O!/1 @Prod-
uct*
9R;%R, "9.
#$'
Example 4.7. Usage of the @Product Annotation
@Product
public abstract class Bike
{
@Product.Name
public String getName() { ... }
@Product.Description
public String getDescription() { ... }
@Product.Price
public BigDecimal getPrice()
{
return new BigDecimal(0, new MathContext(2))
.add(basePrice)
.add(frame.getPrice())
.add(fork.getPrice())
.add(wheels.getPrice())
.add(getEquipmentsPrice());
}
@Product.Asset(name = PRIMARY)
public byte[] getImage() { ... }
@Product.Attribute(label = "Total weight", level = STANDARD)
public int getWeight() { ... }
@Product.Attribute(label = "Robustness factor", level = SPECIAL)
public double getRobustness() { ... }
...
}
Runtime Representation
4 "
%4!AH+
HR;%$%$2NOB%Product2
&6R92!"0%"%
4"%D
2."%4C
6%
4.4.3. Configuration Modeling
.2!!!
!%
2.
"*
Table 4.11. Configuration Modeling Concepts
8 $
@Selectable 92
6 %
@Configurable 92
9 ,
#$$
8 $
".
%
@Constructible 92
"%
@Variable
%
@Parameter "
."
%
@Calculated 2
%
@Configured
%
42@Selectable2@Configurable@Constructible2
%46"
R$%'%#2
N9+9 O%D!
%
4@Variable2@Parameter@Calculated"
. %1"2"
"6R$%#%'2N&*99O%
42@Configured26"
6%
4.4.3.1. Specification Methods
+"22!
" %0"
@Selectable2@Configurable@Constructible
"%1"22@Con-
figurable%
2
%02!!!
6%
Selection
46 2"
"A&82R'%$%$%;2N8 OB*!
2!5!"2
%2&48"2!2
"2!6%
2 HH%
89 2!!A36R;%F2N,
9OB*
9R;%R, "9.
#$;
Example 4.8. Modeling Selectable Components
@Product
public class Car
{
...
@Configured
private Motor motor;
...
}
@Selectable
@Component
public class Motor
{
private FuelType fuelType;
private int power;
private BigDecimal price;
...
}
4@Selectable" 2Motor%
42"
!2!
! %
4"2 "
% R;%#<2N9O
*
Figure 4.15. Component Selection Schema
&!2
AB @Domain.QueryA
R;%;%;%#2NOB%
9 ,
#$<
+" A% %2B"
7AB2 6"AMotor
B! %
E @Selectable2 2
""H"H2 R;%#?2N9
O*
Figure 4.16. Incremental Component Selection
2Motor!" @Relational
AR;%;%<2N9, OB2
"2@VariableAR;%;%$%'2N9 &OB%
42*% %2!
DieselFuelType2Power5250
100"2"!%4
%42!Power802
!"6FuelTypeGas2
!" "!Power80%4
26AH9
HR$%$%$%<2N&OB%
&.2%%
@Parameter%7.
72262
%
Configuration
89 ". @Config-
urable%&R$%'%#2N9+9 O2
9R;%R, "9.
#$?
!%%2
!7."A!
!2!B%
&6 2.!!*!!
"!!" 2
%9!!2!222"
5%2widthheight
%"2 2"!"6
. @MaxAR;%;%<2N9,
OB%
89 2/ !!
!36R;%G2N, 9 2+.9
O*
Example 4.9. Modeling Configured, Parameterized Components
@Configurable
@Product
public class Window
{
@Variable
private Form form;
@Variable
private Material material;
@Parameter
private int width, height;
...
}
Window"@Parameterwidthheight2
@ConfigurableA"@Constructible2!B%
2"Window2
%2%4"2
6 A' formmaterialB%
42AwidthheightB
%
R;%#@2N99 O "*
9 ,
#$@
Figure 4.17. Component Configuration Schema
.2"2
AR;%;%;%#2NOB2*
2!
%
4 5 !
! %4@Relational"
!@Configurable2"@Parameter
2 AR;%;%<2N9, OB%
Construction
&"". %+"2
A182R'%$%$%;2N8 OB2
2"%2
6""%
62*!
2
256%
89 2!236
R;%#(2N, 99O%
9R;%R, "9.
#$F
Example 4.10. Modeling Constructed Components
@Constructible
@Product
public class Kitchen
{
@Parameter
private int length, width, height;
@Configured
private Countertop countertop;
@Configured
private List<Unit> floorUnits, wallUnits;
...
}
&2"!
2!"2 2
!"%
1"2@Constructible"@Variable2
% 2"
%&"2
!5 2!!""5"%
2"2
"%42""A
B%
R ;%#F2 N9 9 O 6
"*
Figure 4.18. Component Construction Schema
9 ,
#$G
2
%
R;%#G2N9,O!6
%22.
%4!67
%
Figure 4.19. Comparison of Specification Methods
D 2!
"%
&2
%1"25
"2! " ""%
4.4.3.2. Configuration Attributes
&".%
562!"
"%2!!
2"@Variable2@Parameter@Calculated2%
9R;%R, "9.
#;(
R;%'(2N9&4"O."
"%D!6!
%
Figure 4.20. Comparison of Attribute Types
Defaults and Regular Attributes
D!
2! !*
#% $0 !
2 R;%#G2N9
,O%42"2@Selectable
2@Configurable
@Variable@Constructible
@Parameter%
'% @0 !
2%
&A% %2
B
%&"!"2 ""%0!2"
" "2!%
922priceMotor R;%#?2N
9O2! % 2
9 ,
#;#
"C%2""
%
- 6
AR;%;%<2N9, OB%
Variable Attributes
&2"" 2
@VariableA B%"2
22A
R;%;%;%#2NOB%8!2!6%
2
5%!"
2"2
2!2626%0!2"!
%
: 2
6%22
"%
&6material36R;%G2N,
9 2+.9O%
Parameter Attributes
E%62String2long2double2
floatint"!";;%
4289 !@Pa-
rameter%
+!"!!*6
2"
A9+B;<"" "!%2
2
"2%8!2"
%
4"6length2widthheight
!36R;%#(2N, 99O%
Calculated Attributes
+72%,
6 2!22
5%
36R;%##2N @Calculated&O!6
*
;;E 2 " 2 " * 5 6 2 6 long
ALong.MAX_VALUEBintAInteger.MAX_VALUEB6double%0!
2 5!2!!""5"
%
;<4" "
A9+B "C!2
R@%'%#2N9+=9 O%
9R;%R, "9.
#;'
Example 4.11. Usage of the @Calculated Annotation
@Configurable
@Product
public class Window
{
@Parameter
private int width, height;
private BigDecimal pricePerSquareMeter = new BigDecimal(125.5);
@Calculated
@Price
public BigDecimal getPrice()
{
final int sqm = width / 100 * height / 100;
return new BigDecimal(1, new MathContext(2))
.multiply(new BigDecimal(sqm))
.multiply(pricePerSquareMeter);
}
...
}
4"289 !
2!!"
@Calculated%4 !""" "
22!" %
,22
" %&6
/5static%4
!%
E"26"2
.%289 5!!
2
6% "!2
!"!;?%
4.4.3.3. Configurable Parts
"289 @Configured
6"%2
* "@Configured2"
%8!22"5
@Configured"%
36R;%#'2N@Configured&O! motor
2gearbox*
;?89 ! "6"
%2 @PropertyDependency({ "width", "height", "pri-
cePerSquareMeter" })"width2
heightpricePerSquareMeter%4!"2! H9 !
= [H%
,
#;$
Example 4.12. Use of the @Configured Annotation
@Product
public class Car
{
...
@Configured
@Part
private Motor motor;
@Part
private Gearbox gearbox;
...
}
&""2@Configured2
@Selectable2@Configurable@Constructible
R;%;%$%#2N,O%
D5!2!."!.
A.B%289
627
"%D56R;%<2N9 +
O%
62!!!2!89
%42! %
4.4.4. Data Modeling
1"!2!".5 !
%2!""
! %4"
"!A
@SelectableB%
0!2"!*R'%'%?2N,
9.O2!("
.%42!5
! "%2"5
"" 2%8"
!!22!
%02
%
62!5!!"
%4! R;%;%;%'2NO!
2!"
%"2R;%;%<2N9, O2
5%
4.4.4.1. Domains
& 2!!2!/ !
%0!2
! * %
236R;%F2N, 9O!Car
Motor."fuelType2powerprice%
9R;%R, "9.
#;;
D"Motor
2%&6R'%#%'2NO 2
"2%
425 Car *
@Product
public class Car
{
@Configured
private Motor motor;
...
}
@Selectable
@Component
public class Motor
{
private FuelType fuelType;
private int power;
private BigDecimal price;
...
}
E!2! Car2! !2!
MotorPD=Motor
P
4!*!%2
55%
2!2!"A
-R$%#%'2N&*99OB% R;%'#2
N, 16O !8
9 !%
Figure 4.21. Morphological Box for Domains
Domain Characteristics
2! % C
2!%1"2
,
#;<
R$%#2N1,,)+, O2!
%0!26"%
0 2
"2R$%#%#2N9*
O%4!22 "2
7%
2R;%<%'2N369 +O!!2Bike
!Equipment%D Equip-
ment2!LockBasket%4
!"2 Lock.class
Basket.class%
R;%''2N--94"O2
C*
Figure 4.22. Runtime Representation of a Component Type Domain
82""2!"
6% !"A% %2EquipmentB2"
"" "A% %2LockBasketB%
8!289 "
2R;%;%;%#2N94"O!%
80 4
%4!%
25!*
L8230 "22
"%02
%
L 230 8!2"
2 %022
9R;%R, "9.
#;?
"*AB26
%
R;%'$2N9:&:O
!*
Figure 4.23. Component Level and Attribute Level Domains
2"5%
10 &
%2!%
4!!"*
L 230 422!
2!
%%
L1230 4
2! "
%
D!6!%
0!2%
5*
L0 @Selectable2
6"%
L 0 @Configurable2
% 2
" %
A@VariableB2A@ParameterBA@CalculatedB%
L 0 @Constructible2
2%
$ 0 4
R$%#2N1,,)+, O6"2
""%2
""AR;%;%$%#2N
,OB%
,
#;@
&2"AH
.H!B*2
AB%" 2
A)B%
E26"(2
".56%2"
""!
""6"AR;%;%<2N9,
OB%
$0 4"22! "
5 %4."*
L!0 &"" 22
AH9
HR$%$%$%<2N&OB%
2
%
L5"0D" !2!"6
%4 "65
7"6"A"!"B%
L!0 4%&
AB2
%& "2
A"B%1"
" "22
"AI-'((?2%<@JB%
L<0 45!%D
"22."
! %
LC0 45"=!
"A% %2B%
%;@
&x"2!x <
10000%&22"2!
x <= t2!t2!5
"AHH!B%
Domain Definition
489 !!"6%1
2!! !
%
""="5/"%
26boolean"
truefalse%
;@E "2/"integerA$'2'$'B2longA?;2
'?;B2floatA$' BdoubleA?; B
A% %2Integer.MAX_VALUEB2"5
!%
9R;%R, "9.
#;F
& ) " 2
% 2)
*
230 &26
%02! 2!
)%
"2"/2
A% %2@Domain("black", "white", "silver", "red", "blue")B%
#)2)A% %2" 7"
@Domain.QueryB%
3""A
B%
!"0 )2
"%62"
@Max(1000)2A6B1000%4
"2""AR$%#%$2N9*-OB2
!2%0!2
2 7"62!!"
"22%;F
3"262
52!!"
!%4 !2!2!
6%1
"!%
R;%';2N9O.%
Figure 4.24. Domain Definition Concepts
& 2
"*)%
;FE89 !"5 "%2"
! 5%&6
%
,
#;G
&25" 2"
2!6"
%
E!5 !
"%9R;%;%<2N9,
O%
Component Type Domain Definition
" 289
! *
0 4./
5"%02"2"
""%
!"0 4"""
! *
Table 4.12. Type Domain Annotations
8 $
@TypeDomain 2
3"%4
"65"%
&"89 %
36R;%#$2N364"O
"2 @TypeDomain%
Example 4.13. Implicit and Explicit Definition of Type Domains
public abstract class Bike
{
...
@Configured
public Collection<Equipment> getEquipments() { ... } ❶
...
}
public class CityBike extends Bike { ... }
public class MountainBike extends Bike
{
@Configured
@TypeDomain({ Lock.class }) ❷
@Override
public Collection<Equipment> getEquipments() { ... }
}
public abstract class Equipment { ... }
public class Lock extends Equipment { ... }
public class Basket extends Equipment { ... }
❶4Bikeequipment!6TypeDomain%
42"%
97"2! CityBike2"equipment
"Equipment*LockBasket%
❷DMountainBike27A" getE-
quipments() B2 ! " Lock "
@TypeDomain%
9R;%R, "9.
#<(
42! MountainBike2" Lock7%
Attribute Value Domain Definition
89 ! *
0 4
5/"%4! *
Table 4.13. Implicit Attribute Domains
#$
boolean 122*true
false
byte2short E2
integer2long2float2double E2
char2String 9= 2
EnumAB "22*
Enum.values()
byte[]2InputStream 1"2
4C!Boolean2Integer2%!"7A!B
72boolean2int2%6"%
!"0 4
!"" ! /A
B2"/" A
B*
Table 4.14. Attribute Domain Annotations
8 $
@DomainA
B
2
3%4
"String
"
"5valueOf(String)%
4@Domain
"A=B%
@Domain.Query
AB
2
6
&!"7"5value%
47"""
AHHR<%'%'2
NOB%
2!"
7C! "%
1"" 5name2
76
(AI/-$#@'((G2%$<#JB%
4@Domain.Query
A=
B%
&89
%
,
#<#
3"2@Domain.Query!"
2"2 " ! %
D289
%
36R;%#$2N364"O
Bike2Wheels2ForkFrame%
Example 4.14. Implicit and Explicit Definition of Attribute Value Domains
@Selectable
@Domain.Query ❶
public class Wheels
{
private String manufacturer;
private double treadDepth;
private BigDecimal price;
...
}
@Selectable
@Domain.Query("select f from Fork f where f.special = false") ❷
public class Fork
{
private boolean suspension;
private double suspensionStrength;
private BigDecimal price;
private boolean special;
...
}
@Configurable
public class Frame
{
@Variable
@Domain({ "16", "20", "24", "26", "28" }) ❸
private int size;
@Parameter
private double height; ❹
@Variable
private Color color; ❺
...
}
❶Wheels2
"" @Domain.Query%4"
7"Wheels
Amanufacturer2treadDepthpriceB%
❷Fork
%4@Domain.Query"2!
67"%+"2suspen-
sionStrength2!"A!
B%
❸4 "Frame
%size6"2
@Domain%
❹4height"2double
%
9R;%R, "9.
#<'
❺4color5"
/"Color%
Part Value Domain Definition
289 ! *
0 6"
!289
5*
L0 @Selectable289
!@Domain.QueryA!B%
L 0 @Configurable2!
2! !
%2!
@Domain.QueryA!B%32!"
%
L 0 4!"
%
!"0 4""
! ";G*
Table 4.15. Part Domain Annotations
8 $
@Domain.Query
AB
2
6
&!"7"5value%
47"""
AHHR<%'%'2
NOB%
2!"
7C! "%
1"" 5name2
76
(AI/-$#@'((G2%$<#JB%
4@Domain.Query
A=
B%
&89 %
3"2! *
#% 89 @Domain.Query5"2
%
'% 8!2"22
"5"!@Domain.Query289
%
;GE*@Domain.Query2%2
2"%
"5!%4" %
!%
,
#<$
$% "289
%
E89 "@Selectable
@ConfigurableA% R;%#G2N9,OB%@Con-
structible#' "2
%%" %
36R;%#<2N36+O!
*
Example 4.15. Implicit and Explicit Definition of Part Value Domains
@Selectable
@Domain.Query ❶
public class Wheels
{
private String manufacturer;
private double treadDepth;
private BigDecimal price;
...
}
public abstract class Bike
{
@Configured
public Wheels getWheels() { ... } ❷
...
}
public class CityBike extends Bike { ... }
public class MountainBike extends Bike
{
@Configured
@Domain.Query("select w from Wheels w where w.treadDepth > 0.5") ❸
@Override
public Wheels getWheels() { ... }
...
}
❶&@SelectableWheels@Domain.Query2Wheels
7" 2!Wheels
%4@Selectable%97"
@Domain.Query"%
❷4BikeWheels2%D
CityBike 289 @Domain.Query
Wheels%
❸ MountainBike 2 wheels5 A" get-
Wheels()B2! "!treadDepth
0.52"@Domain.Query%
2!52!
%
4!"2"*"
22 2
"! %&"26.
"7!%4
!" *
"" !%
9R;%R, "9.
#<;
25"AB
%462!%
4.4.4.2. Defaults
&AR$%$%$%;2N9
9OB289 ! /
%462"
R$%#2N1,,)+, O
!
%
&2!2 %
89 ! ! *
0 "289
4R;%#?2N1O*
Table 4.16. Decision Default Behavior
0 $ $< !"
$
% 9" E%4"6
%
E
% 97"
4""
2"2
7"%8!27"
0%
E
% 9" E%4"6
%
X
% 9.
E%% X2
"%
% &7" 4""
2"2
7"%8!27"
0%
E
% & 4"2"2
%8!2
"6%
X
36 26"2"
89 %
!"0 4 .
7"2!!"
%289
! *
Table 4.17. Default Value Definition Annotations
8 $
@Default
AB
2
&!2
5"%4
"
"
"5valueOf(String)%
4value6%
,
#<<
8 $
4@Default
"A=B%
@Default.Query
AB
2
6
&!"7"5value
2!6""
%
7"2!"
7C! "%
1"" 5name2
767"%
467"5
"2!
%
4value6%
4@Default.Query
A=
B%
&8
9 %
4! "*
L"*! 6
2%4
%
L""2
%026!2
A6!B%
L &!"
%
L"*
2 36
"%
36R;%#?2N36O
@Default*
Example 4.16. Implicit and Explicit Definition of Default Values
public class MountainBike extends Bike
{
@Configured
@Domain.Query("select f from Frame f where f.type = 'MTB'")
@Default.Query("select f from Frame f where f.type = 'MTB'" +
" and f.default = true") ❶
@Override
public Frame getFrame() { ... }
...
}
@Configurable
public class Frame
{
9R;%R, "9.
#<?
@Variable
@Domain({ "16", "18", "20", "24", "26", "28" })
@Default("24") ❷
private int size;
@Parameter
@Default("#{_this.size * 2.5}") ❸
private double height;
@Variable
private Color color = Color.BLACK; ❹
...
}
❶MountainBike2frame56"
!2typeMTBdefault
true2" 7"%
❷MountainBike25!"7"
"2"%size22
24%
❸4@Defaultheight!6
"" %
❹4color "2!Color.BLACK%
Frame!"2 7@Default("BLACK")!
%
D5! %
,"2!62!"
/"!" %
62!!!2!
%
4.4.5. Constraint Modeling
1"2
%89 !
/2"1
I/-$($'((GJ%
289 !1
2! "/-$($
%"2! ""!
%& "!1
AI/-$($'((G2%;JB289 "
%
936R;%#@2N9& O2!
/-$($@Max6/1"*
Example 4.17. Constraint Annotation Usage
@Configurable
public class Window
{
@Parameter
@Max(200)
private int width, height;
...
}
9,
#<@
&widthheight289
"" %
2@Max212
int!2!
!%2widthheight7
200%
21"A
R$%#%$2N9*-OB"%0!2
.2!%
4.4.5.1. General Constraint Characteristics
2"2"/-$($2
! 7"%97"289
7%1 2!!
%
,"!7
R;%'<2N)89 9O*
Figure 4.25. General Structure of OpenConfigurator Constraints
4%89
"%4
2! %42
"A= B%! 2 "
"a%45value)
"%DStringA"
"B262
"A"B%D6 "b%
Constraint Usage
1"2!"!2"
236R;%#F2N9& ,O
!*
9R;%R, "9.
#<F
Example 4.18. Constraint Annotation Usage Methods
@Constructible
@Max(target = "#{_this.length}", value = "#{_this.roomLength}") ❶
public class Kitchen
{
@Parameter
private int roomWidth, roomLength, roomHeight;
@Parameter
@Max("#{_this.roomWidth}") ❷
private int width;
@Parameter
private int length;
@Parameter
@Max("250") ❸
private int height;
...
}
0 ,"22
22! 2!"A
❷❸B%2766
"6 "A❷B<(%
46!*H4width56
roomWidthH%4@Max❸
2505 %
0 &2"7
22"
6"❷%0!2"
<#%
&"25"" 6
!lengthroomLength* @ScriptAssert<'
*
@ScriptAssert(lang="javascript",
script="_this.length =< _this.roomLength")
0!26"2
"""6%D6
2!2*
L %
L " %
L 22<$%
<(E1
A0 B2 ! ! 89 !2 6
" 5 " !% 2 " 6 "
%*==%C%=!=1&:';("*==%C%=
!=1&:'$@2/#;2'(#'%
<#"25"".2%
<'4_&0;%#2*==%C% =
==;%#== ====&%2/#;2'(#'%
<$&R;%;%;%#2NO2
"%" %
9,
#<G
Conditional Evaluation
4condition2!
6%6true2
%false257"
%
4 condition! 6
"%: "2%9
! 6*
@Max(target="x", value="y", condition="a == b")
D 62* %
& 2"""8
9 !"%
D!2!89 !2
6%
4.4.5.2. Supported Constraints
1"""1A@NotNull2@Null2@AssertTrue2
@AssertFalse2@Max2@DecimalMin2@Min2@DecimalMax2@Digits2@Size2@Pattern2@Past2
@Future2@Valid262I/-$($'((G2%#(###'JB2"
289 %
&" 62!!
""!"%&2
%
4! !%2
! 62&6R&2*
:&0 "289
@Equals2@NotEquals2@Min@Max2!
A%%equals/CB2 2 %
0 -"2 6"
@Cardinality2! @Cardinality.Min
@Cardinality.Max%
,"2 2 %
&"2!"2!7"2
"@OptionalA7@Cardinality.Min(0)B@RequiredA7
@Cardinality.Min(1)B%42%
0 36 " "
A B% D " "
A@Compatible.TypeB " A@Compatible.MatchesB2
A@Compatible.ElementType2
@Compatible.ElementMatchesB%
,"2 "
!* 2
9R;%R, "9.
#?(
"
% , 2 "
%
0 36 " "
A B% 4"
" % 4"5 7" 2 !
5 6 % 2
" ! 7* " "
A@Incompatible.TypeNot2@Incompatible.ElementTypeNotB
"A@Incompatible.MatchesNot2@Incompatible.ElementMatchesNotB%
" 0 &2 6 @Satisfies
@Relational%1/"%4
7@ScriptAssert%
"2truefalse%42@Relational2
"%42
2"A
R;%;%;2N, OB%
& 2&6R&26 %
D2
2.
%
D 9R?2#$
2!".!.%
4.5. Configuration Procedure
9 2
2!2
%E!2!! *!52!
22
%!2! 2!
6!!""
%
22."89 !!
%D C
2!! 6%
4.5.1. The Object-Oriented Configuration Procedure
R;%'?2N48C89 +O !
."89 !%
1"2
R$%'%'%#2N4)9 +O%42!!
C 2!*
48C89 +
#?#
Figure 4.26. The Object-Oriented Configuration Procedure
Configuration formulation<;
& ! 2
2! ❶%C
222
2/%D!"%
4"2!"
%❷%,2
❸2!2
%4" 2
R$%#2N1,,)+
, O%42 2
%&"2
" " %<<D
.2
%
<;E89 2 2"=
AR$%$%$%;2N9 9O"R@%#%'2N9.
OB2! 7
%
<<9"27 2!!"89
AR$%$%$%;2N9 9
O"R@%#%'2N9.OB%
9R;%R, "9.
#?'
Configuration synthesis and evaluation
E62"
❹%4 " R;%'@2N&
+9 +O%
Figure 4.27. Abstract Specification Process for Configurable Products
0 4
R$%#2N1,,)+, O%
2 2*
L6 ❺%4 !2
@SelectableAR;%;%$%#2NOB%
L0!❻%4
@Configurable@ConstructibleAR;%;%$%#2N9
O"R;%;%$%#2N9OB%
2"7%
2 2!"%
42A@Variable
@ParameterB❼A@ConfigurableB❽*
80 5""2
""*
L22
L25AH.H
R;%;%;%#2N9OB%
62 %,2
"@Required2 %
369 +
#?$
10 " 2(2
7AR;%;%#%$2N+OB%4
52"22
"AH9"
HR;%;%;%#2N9OB%"2"
% 57"2"
""AH9"HR;%;%<%'2
N9OB%
4 2!
%
Configuration Interpretation
&R;%$2N4)9 ,O2
6 22
/C%D "
!" "❾2
"! C%42
2❿%
4 22!!
6%D!6 "
6%
4.5.2. Example Configuration Procedure
9 R;%'F2N9 ,9
.1A36BO6" %E!
"26"
%62 29R?2#$
"&6R12#)-63%
Figure 4.28. Configuration Domain Model for Customizable Bikes (Excerpt)
4Bike2Frame2Wheels
"Equipment%DBike"2MountainBike2CityBike
9R;%R, "9.
#?;
ElectroBike.%&ElectroBike" Motor
%&Equipment" LockBasket
.%
42Bike2MountainBike2CityBikeElectroBike
%4"5@Product%4 2Frame2
Wheels2Lock2BasketMotor@Component%D
"@Configurable22"2
"6Frame@Selectable%42!"
6 2! .
%".6%
Equipment2"2
!"ALockB ABasketB%
E!2 " Bike"
%-"2 !Bike
"%4!ACompo-
nentDescriptor2R;%$%#2N3)9 ,,
,OBBike.
"%
4 !,:C
R;%'G2N#*.,& O%
Figure 4.29. Step 1: Initialized Model and Agenda
4Component2PartAttribute"
R;%$%'2N,, O% "6"
"2specifiedfalseA4R;%;2
N9OR;%;%#%#2N-OB%,2abstract
biketrue2 "
"%97"2bike""
instantiated %1!2!6"
"A67B2
.%
4 .2
%& 2"
369 +
#?<
R$%#2N+,O%E! 6
7AB2""%
62"" 5"2""
%2""
*2 bikemanufacturer%
" "%
H /H!5*"
""%
Figure 4.30. Step 2: Bike Type Specified
E2bike2ElectroBike
5"%4 . R;%$(2N'*14"O%
4!" motor2
2 %"289 .
ElectroBike"" /1
2 "bike%4 %
,2 "".!
*%done%
motor%
E62!frame5A
B*colorSilver5%4
2Color2/"%
labelMyBike%
& R;%$#2N$*&O2
".! 5%
9R;%R, "9.
#??
Figure 4.31. Step 3: Frame Attributes Specified
;2wheels" 6
!5AB%62
"%
4 ! R;%$'2N;*DO%
Figure 4.32. Step 4: Wheels Specified
E62!7*%&R;%<%#2N4
8C89 +OH9 "H2
!*27"equipment
A(B%4 "!2
equip12 %4"!"
%
369 +
#?@
& R;%$$2N<*37&O2 "
. "%
Figure 4.33. Step 5: Unspecific Equipment Added
72Lock
"equip1AB
Lock5AB%
4! R;%$;2N?*37O%
Figure 4.34. Step 6: Equipment Specified
"2motorAB2!
%2!
"2 %
9R;%R, "9.
#?F
4 R;%$<2N@*9 9O%
Figure 4.35. Step 7: Configuration Completed
4 "%42 /1
"ElectroBike! R;%$?2N9 ,-8CO%
4 2"22
%
Figure 4.36. Configuration Model Result Object
46! %D5! !
C!89 !
"%! 2!5"
%
4.5.3. Configuration Agenda
Configuration Process versus Configuration Agenda
2%,2
2!"%&
2"%
9 &
#?G
0!26!2! 2!
"272!
6%2
2 R;%$@2N9 +!O%
Figure 4.37. Configuration Process as Screenflow
D89 "!"
A!B26!!"
%
422"
%D" "72 2
%
2!
.AB%4!
R;%$F2N9 +9.O%
Figure 4.38. Configuration Process Customization
Configuration Agenda Characteristics
& 2. %
%02
%
9R;%R, "9.
#@(
&222
%4 R;%$G2
N-!9 242)9 ,
O%
Figure 4.39. Relationship between Configuration
Decisions, Tasks, and the Generic Configuration Model
❶4
R$%#2N+,O %
❷4 6
7"". %
❸3"2 !
%
D5 C
R$%#2N+,O%D5
!%
9 .!%&*
L 2
L"2
L A% %2
"B2
L2 AB
2
L"2 "
A!2 " )2H
.HR;%;%;%#2N9OB%
E"2289 !"6
".5!
"%4"2.!89 5
AH)9 ,HR<%'%'2N9
9 OB%
9 &
#@#
Agenda Task Types
4Task5""! R;%;(2N& 44"0"O*
Figure 4.40. Agenda Tasks Type Hierarchy
4 . Task H H2
Data Validation % 4 " T
5 "2 ! % &
SpecifyComponentTypeTask<T>2 2 Component<T>2 !
SpecifyAttributeTask<T>Attribute<?, T>%4
"Binding<T>2!"TaskCompos-
iteTask%
D! ! 2
! %
Model to Task Mapping
4 "89 4R;%#F2N9
& 4O%4 "
R;%<%#2N9 "O%
Table 4.18. Configuration Agenda Tasks
# $
<
$ $
SpecifyComponentTask E
%
Component<C> Domain<C> 9
%
SpecifyComponentType-
Task 9
"
A%B
Component<C> Domain
<Class<?
extends C>
4
"
"
%
9R;%R, "9.
#@'
# $
<
$ $
SelectComponentTask 9
.
A%&%B
Component<C> Domain<C> 4
%
ConfigureComponentTask 9
.
A%&%B
Component<C> Domain<C> 9
%
ConstructComponentTask 9
.
A%1%B
Component<C> Domain<C> 9
%
SpecifyAttributeTask &
7"
A%B
A%B
Attribute<?,A> Domain<A> 4
"
%
SpecifyPartTask E
%
Part<?,P> Domain<P> 9
"
%
SpecifyPartQuantity-
Task 9
7"
A%9%B
Part<?,P> Domain
<Integer> 4
"
7"
"%
4 "2."%
2!"" @Required
"@OptionalAR;%;%<2N9, OB%
Agenda Task Hierarchy
CompositeTask"2" %
89 2 " "
A "2H H
R;%;%#%#2N-OB" !
5"*
0
89 SpecifyComponentTask 2!
! *
L SpecifyComponentTypeTask2
L "@Selectable2 Select-
ComponentTask2
L "@Configurable2 Con-
figureComponentTask2
L "@Constructible2 Con-
structComponentTask
9 &
#@$
80 A@Variable@ParameterB
@Configurable@Constructible289 Spec-
ifyAttributeTask ConfigureComponentTask
"ConstructComponentTask%
1 0 @Configured @Configurable @Con-
structible289 SpecifyPartTask
ConfigureComponentTask"ConstructComponentTask%
5"289 *
L0 2SpecifyComponentTask5
SpecifyPartTask2%
L10 2SpecifyPartQuantityTask
SpecifyPartTask%,22
SpecifyComponentTaskSpecifyPartTask%
R;%;#2N3640"O6""
R;%<%'2N369 +O%
Figure 4.41. Example Task Hierarchy<?
4Agenda2 Task22"
%
<?EC6 "!
2!!"7%
9R;%R, "9.
#@;
Task State Transitions
"2 *
2 "A!
B%
22
!5"%
&"22"
%42!5"
%289 "2"
%
,22"
%
D!2! "R<%$%'%<2ND !
9 & O%0!2!
89 !62!5"
%
4.6. Summary
2!89
%+"2!! "6
.
%:5". %
D2! !89
% 2.*
L 2
L C2
L 2
L 2
L /%
1"2!89 5
!". %4"*
#% 9."C%
'% 9= %
$% 97"2 7
"%
489 !*!
". 2
%4"2
2/%,
/"!
%
D6
C %,
"2!289 2"
" %
4 6%
"
#@<
"
%4 22."
2!"" %
"2!6 %
62!.
%D6C
/ "%
4C! 2!
89 !*
%4"HH
289 56"
6"%6" 2%
4! !
.%"2 2
R$%#2N+,O2! *
L$0 DEA2
B2 A"B
%
L$0 4@Product
"%
L$0 4.2
" 2
%D2"
<@%,2 2
%
L$0
"2!
%2"%4"
2""
%4"/"6.
%
L$0 42
2" %4
!"2 .
%
D2.2
"%D!6
9R?2#$%
42! *!2!
%D6
"! 6%4!"!!2!
R$%#2N+,O
"!R$%'%'%'2N49
+4+O.89 %
<@42"" 2
%0!2"2 2
2!"!%
9R;%R, "9.
#@?
62!!2!89 56
%
#@@
5
Technical Architecture and Implementation
2!!89 5
%D! 2
&+%
489 5 "
%2!!
.)2"
"%
5.1. Technologies
&R;%#2N489 , "O289
"/! %D
6"/
A222%B289
"!! %4 !
! 2 !%
5.1.1. Java
822/ "!%D
"/5CR;%'2N,
&O%"2/89 *
6;0 /"CA88B C
88 2 A B2"22
2 %+"2
! C
R;%'2N, &O%
8 0 &
/6
9R<%R4&
#@F
%2/2!/<A
"#%<B2"!89 !C
7.AR;%'%$2N+ ,!/&
OB%4" !!"%
,2A&+4B/? "*&+4
"6/2
%&&+4
%D".!89 !2
2&+4".
".%965"
2!"62"
2!""&+46%#
@0 &H H"89
2.89 "%+"2
/1!
" "
/5&+% &+2
6%'
#0 89 "2"
&+ /1%2!
6 "
/%$
5.1.2. Java Persistence API (JPA)
D89 ;2
" !!/+&+C
%&!/"2/-$#@<2!"
'%(2 !C!89
%,"2! !*
$0 2/+&
".//1!
%!+8/8!
!1`:?%4"2
" ""
" "%
>0 /+& 7" " /
1C!"%D"
7"&+"."89 5
7"AR;%;%;%#2N&OB2"
# &+42 *==%%=C=?==
= = =% *==%%=C=?=== ==
) %2/''2'(#'%
' *==%%=C=?=== ==6%2 / ''2
'(#'%
$, *==%%=C=?=== =
= %2/''2'(#'%
;4!89 " ."DataProvider
AHHR<%'%'2NOB%D89 !
/+&22% %2/9-"&+
"/-'F$A*==C% ==C=PW'F$B "%
<*==C% =/="==C$#@=6%2/''2'(#'%
?&%%A"9
1
#@G
7"&+'2"
!%
10 &"/+&'
&+2!!
"%42! /+&"%D
"""89 !2
2! -X
@%& 89 5" "
"/+&5&+26""!!
%
& 2/+&""
%2/+&!7"
AR;%;%;%#2N&OB2*7
"/+&7""%
5.1.3. Bean Validation
41/%
/-$($F!/"%1H
!" CHG
C %689
!2! 1*
$0 1/
C" %2!"8
9 ""1%4!
!!2!
2!/-$($2
%
%0 41"
.!" 2
&+C %
0 " " /+&2
/-$($&+
%
"289 1
" "C%0!2
16"7!2
62""2
"%
5.1.4. Contexts and Dependency Injection for Java EE
(CDI)
E" ! 296
"CA9B2/-'GG#(2" "
@62!/+&5@Id "
!"2""6 %9"2
@Ignored2 %
F*==C% =/="==C$($=6%
G9*==% =2/''2'(#'%
#(*==C% =/="==C'GG=6%2& ;2'(#'%
9R<%R4&
#F(
89 !%4!
*
$;0 9 2
"C.H ! " H##%"
CABC C%2
A""" @Inject
22B
CC%,2
9!"CC"
62 "%
3"2"CC2! *
L "%
L 16"%
L 2%
4! !!"C6
9*
@ApplicationScoped ❶
public interface ValidationProvider { ... }
public class JSR303ValidationProvider
implements ValidationProvider { ... }
@SessionScoped ❷
public class ConfigurationSessionImpl
implements ConfigurationSession
{
@Inject ❸
private ValidationProvider validationProvider;
... ValidationResult<T> validate(Configuration<T> configuration)
throws ConfiguratorException
{
return validationProvider.validate(configuration);
}
...
}
4ConfigurationSession6❷2
!2 044+#'"
6%"2ValidationProvider❶%9
7"2 " C
%DC Configu-
rationSession❸29ValidationProvider"
JSR303ValidationProvider"!6
%
4 ."C2
2!.%
!0 9"2
" =!!
##9*==%C% =!=====#%2/''2'(#'%
#'&%=" 6
96"C/33A9B
#F#
8)#$!AI8)V&'((;JB%95!
2!57
"!%"2"A!
9B%4
. (%
4! !6!9.*
public class Payload {} ❶
public class Sender
{
@Inject @SomeQualified ❷
private Event<Payload> event;
public void emitEvent()
{
event.fire(new Payload()); ❸
}
}
public class Recipient
{
public void onEvent(@Observes @SomeQualified Payload event)
{ ... } ❹
}
62PayloadC❶%4SenderC
9EventC❷29%4C
7@SomeQualified%4
" fireCEventC2
Payload❸%422onEvent
Payload27!@SomeQualified2"
!9@Observes❹%E!2!Sender
29onEvent2 Payload
C"%
ERecipientSender"%2Recipient
Payload"A
7B2! #;%02
!6"%2!9
%:!2
2%
60 927
62!%4*
L0 ,!&8+#<
#?%"C
!"%
&""%
62"2 " 5
2#@%
#$"%1!"
#;*==%!% =!=8V2/''2'(#'%
#<&%!
#?*==%C% =!=====%2/''2'(#'%
#@ 6 " 92 *==!!!%!% =
='(#(=($="!C'=2& ;2'(#'%
9R<%R4&
#F'
L$0 D9! .#F%
82 "%42
"!C"!"%
& 2689 2
.""#G%"2"
2 27%4
26.22
% 52
" "%
L1"0 D)29
6%4!"!" !9
"2 9%
489 !962
9%4!22
% 289
"/%
89 " 95"C"
%1"
"%9"29C
89 5)2)22
!*
$;0 3" !
@Inject29%4*
L 2" "
! !"A"B
L "!
"2 "A% %2
22%B 9A6"26"2
"B
L"AB2 2'(
A"B
!0 ," !CA% %2!
ConfiguratorConfigurationSession2CComponent2Attribute
Part2%!B!"2"
9%62!! 289
ConfigurationSession'#7!@Initialization"7%
4! *
L .62
A6"B
L .! 5
A"B
L .2 6
!A6"B
#F*==%C% =!=====%2/''2'(#'%
#G36*==!!!%%=!='';((#?F$#=+$"C/
33?2& ;2'(#'%
'(*==%!% =!=,VC2/'$2'(#'%
'#,"2ConfigurationSessionImplementor2!Con-
figurationSession2"%,R<%'2N&
8!O%
&8!
#F$
2"C"9
2!2!6"2
"2"6"6%
D95A22%B!
!22 89 "
25"""%2!2
!C 9"
""9%
0 !
89 !2!!!5
%
5.2. Architectural Overview
2!!89 5%D
! 2 ! !
!.% R<%#2N&8!O
2!5H H%
Figure 5.1. Architecture Overview
9R<%R4&
#F;
5.2.1. Multi-Tier Architecture
2""289
''%62
!*
1&0 4"
!%4"" "89
2!2""A% %2
! "'$9R?2#
$B!"!"5!%&
"289 ! /
A% %23-9+';B%
9!5 A
!B" !"2" '<%
:0 489 !" 7
%4"*
L 0 4&+
" /1 89 %
!"/,'?2
"2!" &+%
L!"10 4)%"'@"
!2 %4+
89 6!
!"%
L0 489
"!%+"2
"%
L1A 0 "289 "
'F2!""2
!6!5" %
$0 :""289 "
= =6"%
89 26"2"
2"+,23-+29-,9&!%
D" /2
"/%
489 5
%! 2!!
"!%
''*==%!% =!=,V2/'<2'(#'%
'$*==%=2/'<2'(#'%
';*==!%% =6%=-V9V+2/'<2'(#'%
'<E*!"%
'?&%,$
'@&%+
'FE*" %
99
#F<
5.2.2. Client Configuration Interface
489 !
2! &+
%
D!6!R<%$2
N&+ *D !89 O%
Configuration API
4!"/2!
! !
"%&Configurator"
&+%4&+!! *
0 4A"/Con-
figurationSessionB
%D !6
2 %42
! %D
"!"2!"2
5"!"044+A
B!/33!6%
4ConfigurationSession
A!B%Configurator
"C%
& ConfigurationSession C2" " Configura-
tionSessionImplementor 2 ! 89 "
A@Initialization2@FinalizationB9%
80 4 ConfigurationA-
genda%4"
2 A
R;%<%$2N9 & OB%
2
*!72!!
%&2
%2 2&+
%
0 &R;%$2N4)9
,O2HH89 !%
!&+
%,2.
! 2
%
4 ".Config-
uration2Component2AttributePartAR;%;%#2N, OB%4
ConfigurationC
%&Component<T>
"T22C "%9
C2""ConfigurationImplementor2
ComponentImplementor2AttributeImplementorPartImplementor%
9R<%R4&
#F?
89 "A@Preparation2@Initialization2@Fi-
nalizationB9%"2C
ModelFactory2! 'G%
D2!=
%&R;%$%$2NO289
62 2$(%1"2
"2"6"%2
.29&"
"%7"
""6!AR<%'%<2N+ 9O
R<%;2N+ *36 89 OB%
&"R;%;%#2N, O2
./%422
%4"
262!5 5"
%4""2"""22
A!B"6 %
8"9AR<%'%;2N)3
1OB2 6"!%"2
.2!"
@Initialization%
:$#0D2
" %4
"6"7
2 %2
"!"""2
2"" %4
"ValueChange2TypeChange2%
6$'0D !2"
2&+
$$"% 2SetVal-
ue2SetType%2 26
"%4"
!AR<%'%'2NDOB%
Services
2 ""
%& 2$;*
$10 4MetadataProvider 2
7"22ComponentDescriptor2Attribut-
eDescriptorPartDescriptor/"A
R;%$%#2N3)9 ,,,OB%
$10 4DataProvider"
" %"2
'G*==%!% =!="VV2/'?2'(#'%
$(E;""%
$#4"2!89 %
$'4"2!8
9 %
$$42 2*==%!% =!=9V2
/'?2'(#'%
$;E!!2R<%'%$2NO%
#F@
2!@Domain.Query"
"AR;%;%;%#2N&OB%
9 10 4ValidationProvider22
2!"%
"%
0 &ConfigurationManager2!
"Configuration%&2
""
% 2@Completed Configura-
tion9%4""
6. 6"2
+,23-+9-,%02
! "%
Webservice Interface
89 5 "
%4!-34$<
8&+$?%& 6"
" 044+$@2!"
6"-34"2! -34
!
89 !% 2!89 52
"!8&+!
%
5.2.3. Internal Implementations
D62
""2!
%4! %
Default Implementations
89 !%
4!HH
!%&"9
"C2"
95 "AI/-'GG'((G2
%#@JB%
Default Service Implementations
," 289
C/33$F2"/+&21/&[1%
4*
E@$10 89 5"
/%42
$<&%8#% 2-34"I '(((2
%@?J
$?&%%C!
$@&%=" 6
$F&%,##
9R<%R4&
#FF
!5MetadataProvider/52
"7"6
%
&6"
[,:"%8[,:
/"/"%
&"289 TypeRepository2
7""%4""5"
"2"/
6%
E18$10 1"289 !/
+&+ %
+"2/+&5/+`:$G"7" "
2" @Domain.Query%4
7""6"/+&
%9"289 /+&'%(%
<9910 &289 5
!"1
%289 /-$($
%9"289 1
#%(%
E8F< 0 89 5ConfigurationManag-
er
<9%&"2" /1/&[1
2" [,:2 6
<9%1[,:."/&[1
'%'%
5.2.4. Extension and Integration SPI
&C89 5)
.%"/2!"2
.6" "%
Implementors
4+%&
!"%2
"7"!.%,"2
!!.%D
.256" % R<%'2
NO.!! Com-
ponent6%
$G&%,A"9
36 +
#FG
Figure 5.2. Implementors
2"&+Component
"2!%+"2
"5 .%2
&+""2
%
4"2. 9AR<%'%;2N)
31OB2" @Initialization2 ComponentImplementor
CC="%.""22
". +Compo-
nentImplementor"%
"2"HH89 5
"2!
6.A.B%4
!2!
%
Global Event Bus
& +"95"A
R<%#%;2N96"C/33A9BOB%4
"89 56"6"2"
%4R<%#2N)
33931O! *
9R<%R4&
#G(
Table 5.1. Global Events Emitted via the CDI Event Bus
!&1 > $
5%
BootstrapImplementor R 3
2
%&!
!
%
ComponentDescriptorImplementor2
AttributeDescriptorImplementor2
PartDescriptorImplementor
@Preparation2
@Initialization 9
"%
ConfiguratorImplementor @Initialization2
@Finalization 9 "
%
ConfigurationSession
Implementor @Preparation2
@Initialization2
@Finalization
9
"%
ComponentImplementor2
AttributeImplementor2
PartImplementor
@Preparation2
@Initialization2
@Finalization
9
"%
Component.Event2
Attribute.Event2Part.Event
R :
%
Attribute2Part @Added2@Removed 3"
%
Configuration @Created2
@Stored2@Loaded2
@Completed2
@Validated2
@Submitted
9 "
%
D! *
5%0 "!C%4""
""%4 !
AR<%'%;2N123OB26
2 "%
0 & %4"
!"
%2R;%;%#2
N, O%4"5" 2"
%
0 E"2
%4"22"
7. "6"
AR<%'%<2N+ 9OB%
Bootstrap, Environment and Utilities
&289 "/33!
%"2 ,##@2!&+
+ 9
#G#
$%(29#%(2/+&'%(21#%(/&[1'%'"%1
"289 "2
"!!5/&-"!%
289 "!"6
!" Configurator2!
"ConfigurationSession%
62
89 CEnvironment
" "%! 6
Environment262*
L,##AB2D&-;("
L,%#
L%1
47
2""
%
"289 !%
2"26
""&+7"7""%
5.2.5. Plugins and Connectors
2!5!"2!
"26!5%E"2
"6%
2"!*
10 +6 %6
2 6 2
! . %8
%4.""
!@Initialization ComponentImplementor2
ComponentImplementor.addFacet(Class<F>, F)%
0 &! 89 "2
+,23-+29-,9&%&62
3-+9-," "
"%4"! 2
@Submitted Configuration%
6289 !!
2
"%4+9R?2#
$22A"B !
%
0 89
!262! !&++
%
;(&%>!
9R<%R4&
#G'
5.3. API Usage: Working with OpenConfigurator
2! ! 89
!%2!!!2!&+"
!AB %
42*
#% 1 !
'% +
$%
D!"! %
5.3.1. Bootstrapping and Starting a Configuration Session
9! * !5! /;#
" 1 9R?2#
$A&6R12#)-63B%
!9!/2!5. &7;'
!C;$%4/2!
89 AB""
C%
Bootstrapping OpenConfigurator in a Managed Class
&2! 89 !"
CA&7/! 2$%(
"9B2 89 "*
@RunWith(Arquillian.class)
public class ConfiguratorIntegrationTest
{
@Inject
private Configurator configurator; ❶
@Test
public void testConfigurator()
{
// do something... ❷
}
}
8 "89 !"
"C Configurator" ❶%89
"%&.2 "
❷%
&289 !!
"A 7B*
#% BootstrapImplementor
'% @Initialization ConfiguratorImplementor
;#*==C% =2/'@2'(#'%
;'*==!!!%C% =72/'@2'(#'%
;$4 " /&7" 89 %
1 9
#G$
Bootstrapping OpenConfigurator in a Non-Managed Class
" 9C!"2""
89 !*
public class ConfiguratorStandaloneTest
{
@Test
public void testConfigurator()
{
Configurator configurator =
new OpenConfigurator().initialize(); ❶
// do something...
}
}
X" ! OpenConfigurator initialize
❶%
!2!C
%
Obtaining a Configuration Session
46 ConfigurationSessionC2!Con-
figuration*
@Inject
private ConfigurationSession<Bike> session; ❶
ConfigurationSession<Bike> session =
configurator.createSession(Bike.class); ❷
// start configuration
... ❸
session.load(id); ❹
Bike bike = new MountainBike();
session.restore(bike); ❺
// continue with configuration
...
& 2!!"ConfigurationSession%2
C❶%&"2!2" Configurator
5createSession"❷%
2 AR<%$%'2N+ 9 OB%8
! ❸2" "
❹ /1❺%
289
. "%&"2! A
7B*
#% @Preparation ConfigurationSessionImplementor
'% @Preparation Component=Attribute=Part2
$% @Initialization Component=Attribute=Part2
;% @Initialization ConfigurationSessionImplementor
9R<%R4&
#G;
A/BConfigurationSession2
&6R92!"0%"%
5.3.2. Performing Configuration
0 2
89 &+%9
! *
L E
L &
L "
L D !
L D !
D!!"
2 &+ 2!
" %
5.3.2.1. Navigating through the Generic Configuration Model
4 &+ 2
!! *
// retrieve the root component
Configuration<Bike> configuration = session.getConfiguration(); ❶
Component<Bike> bike = configuration.getRootComponent(); ❷
// get all attributes
Collection<Attribute<Bike,?>> attributes = bike.getAttributes(); ❸
// get a specific attribute
Attribute<Bike, Integer> weight = bike.getAttribute("weight"); ❹
...
// get all parts
Collection<Part<Bike,?>> parts = bike.getParts(); ❺
// get a specific part
Part<Bike, Frame> bikeFrame = bike.getPart("frame"); ❻
// access the component associated to a part
Component<Frame> frame = ((SingularPart<Bike, Frame>) bikeFrame)
.getPartComponent(); ❼
// alternatively, use a shortcut method of the Component interface
Component<Frame> frame = bike.getPartComponent("frame"); ❽
...
assertTrue(frame.getParent().equals(bike)); ❾
2Configuration❶%&
2ConfigurationC 2!Config-
urationSessionAgendaAR<%$%'%<2ND !9 &
OB" %&Configuration
2 getRootComponent❷%
4Component❸
"❹2!7 /1%
+ 9
#G<
2Component
❺"❻%
"2!*
L SingularPart5getPartComponentA"getPart-
ComponentsPluralPartB2!7
"2
L getPartComponent A" getPartComponents
B"Component2"%
45 getParent
%
EC2""AConfiguration<C>2Component<C>2
Attribute<C, A>Part<C, P>B2.2 "%4"
&+!%
A/BConfiguration2Component2AttributePart
!2&6R92!"0%"%
5.3.2.2. Accessing Meta-Data and State Information
4 "
"%& !"!
Component27""AttributePart!*
// get the descriptor of an element
ComponentDescriptor<C> elementDescriptor = element.getMetadata(); ❶
// whether this element or any of its sub-elements
// has been specified in some way by the user
boolean specified = element.isSpecified(); ❷
// get the current JavaBean type of the component
Class<? extends C> currentType = element.getType(); ❸
// whether the current type is abstract
boolean notInstantiable = element.isAbstract(); ❹
// whether the element has been instantiated,
// aka the underlying bean has a non-null value
boolean instantiated = element.isInstantiated(); ❺
D5getMetadata2C
❶%4isSpecified 2
!26""
❷%4getType❸isAbstract❹5
"!"%"2
/1 """%4
isInstantiated!"❺A
R;%;%#%#2N-OR;%<%'2N369 +OB%
5.3.2.3. Specifying Options
+" &+2
" %D2
%! !!2!
9R<%R4&
#G?
R;%<%'2N369 +O!
&+*
// specify the type of a component
bike.setType(ElectroBike.class); ❶
// specify attribute values
Component<Frame> frame = bike.getPartComponent("frame");
Attribute<Frame, Color> color = frame.getAttribute("color");
color.setValue(Color.SILVER); ❷
frame.setAttribute("label", "MyBike"); ❸
// specify part values
Wheels slickTyres = ... // get slick tyres instance ...
bike.getPart("wheels").setValue(slickTyres); ❹
PluralPart<Bike, Equipment> bikeEquipment =
(PluralPart<Bike, Equipment>) bike.getPart("equipment");
bikeEquipment.setCardinality(1); ❺
Component<Equipment> equip1 =
((Indexed<Component<Equipment>>) bikeEquipment).get(1);
equip1.setType(Lock.class);
Lock lock = ... // get lock instance
equip1.setValue(lock);
Component<Motor> motor = bike.getPartComponent("motor"); ❻
motor.setAttributeValue("fuelType", FuelType.DIESEL);
motor.setAttributeValue("power", 200);
D setType Component 2 " " /
1❶%4" "
5"C22Bike6%& 2
"2"
/1%42 62ElectroBike
"bike.setType(ElectroBike.class)%
E62!HHHH
Attribute5setValue❷setAttributeValueCom-
ponent❸%
2!"%4 Part
5setValue!❹%&57"
setCardinalityPluralPart2!"
Part❺%"2 !2!
❻%
"289 /12
"" C%2
R;%;%#2N, O
%
5.3.2.4. Working with Facets
!2!"""&+%
+" 2!2"
%
4 AR;%$%$2NOB%
D5 6%
+ 9
#G@
The Product Facet
4Product%4!
!6"Product*
Component<Bike> bike = ...
Product<Bike> bikeProduct = bike.getFacet(Product.class); ❶
String description = bikeProduct.getDescription(); ❷
Collection<Attribute<Bike, ?>> characteristicAttributes =
bikeProduct.getAttributes(Attribute.IDENTIFICATION); ❸
2Product❶%4getDescription
!@Product.Description❷%02
!
*&+"@Product.Description
2"Product2
"2"&+%
A/BProduct&6R92
!"0%"%
The Configuration Facet
DConfiguration2
*
Component<Frame> frame = ...
Configuration<Frame> frameConfiguration =
frame.getFacet(Configuration.class); ❶
SpecificationMethod specificationMethod =
frameConfiguration.getSpecificationMethod(); ❷
assertTrue(specificationMethod.equals(CONFIGURABLE));
Attribute<Frame, Color> color = frame.getAttribute("color");
AttributeType colorAttributeType =
frameConfiguration.getAttributeType(color); ❸
assertTrue(colorAttributeType.equals(AttributeType.VARIABLE));
Collection<Attribute<Frame, ?>> parameters =
frameConfiguration.getAttributes(AttributeType.PARAMETER); ❹
assertTrue(parameters.contains(frame.getAttribute("label")));
Component<Bike> bike = ...
Configuration<Bike> bikeConfiguration =
bike.getFacet(Configuration.class);
PartType wheelsPartType =
bikeConfiguration.getPartType(bike.getPart("wheels")); ❺
assertTrue(wheelsPartType.equals(PartType.CONFIGURED));
&2 ! Component
5getFacet❶%4Configuration
2 2
R;%;%$2N9 , O%
4getSpecificationMethod!
"22SELECTABLE2CONFIGURABLECONSTRUCTIBLE%4
"/"SpecificationMethod❷%
"2"REGULAR2VARIABLE2PARAMETERCALCULATED
"AttributeType7
9R<%R4&
#GF
getAttributeType❸%4Configuration
getAttributes(AttributeType)
"❹%
4 PartType " REGULAR CONFIGURED
%&Configuration
2 getPartType(Part)
getParts(PartType) 5" "
"%
A/BConfiguration&
6R92!"0%"%
The Data Facet
4 Data2&+ 2
%"2
2R;%;%;2N, O%D5
*
Component<Bike> bike = ...
Data<Bike> bikeData = bike.getFacet(Data.class); ❶
Domain<Class<? extends Bike>> bikeTypeDomain =
bikeData.getComponentTypeDomain(); ❷
assertTrue(bikeTypeDomain.isEnumerable() &&
bikeTypeDomain.getSize() == 3 &&
bikeTypeDomain.contains(MountainBike.class) &&
bikeTypeDomain.contains(CityBike.class) &&
bikeTypeDomain.contains(ElectroBike.class));
Component<Frame> frame = bike.getPartComponent("frame");
assertTrue(frameData.getDomainScope().equals(PROPERTY)); ❸
Attribute<Frame, Color> color = frame.getAttribute("color");
Domain<Color> colorDomain =
frameData.getAttributeValueDomain(color); ❹
assertTrue(colorDomain.isEnumerable() &&
colorDomain.getDomainType().equals(SYMBOLIC));
for (Color definedColorValue : Color.values())
assertTrue(colorDomain.contains(definedColorValue)); ❺
Attribute<Frame, String> label = frame.getAttribute("label");
Domain<String> labelDomain =
frameData.getAttributeValueDomain(label); ❻
assertTrue(!labelDomain.isEnumerable() &&
!labelDomain.isBounded() &&
labelDomain.getDomainType().equals(LITERAL));
Part<Bike, Wheels> wheels = bike.getPart("wheels");
Domain<Wheels> wheelsDomain =
bikeData.getPartValueDomain(wheels); ❼
assertTrue(wheelsDomain.isEnumerable(10));
Iterable<Wheels> wheelsValues = wheelsDomain.getValues(); ❽
...
& 2 Data Bike
Component.getFacet(Class)❶%2!5
getComponentTypeDomain❷%4Bike5"
+ 9
#GG
"!2!!"6"
"6 Bike2"MountainBike2CityBikeElectroBike%
E62!5 Frame%
@Configurable!@Domain
2""A36R;%#;2N
36&OB2
2"DomainScope.PROPERTY❸%&
getAttributeValueDomain(Attribute)2!
.DomainC❹%4color
2"Color"❺%4label5
222%
"2 " Data %
getPartValueDomain(Part)Data2DomainC
5❼%47
"2!R;%;%;2N, O%
! 2102
getValuesDomainC❽%
1"2Data!
2R;%;%;%'2NO*
Component<Bike> bike = ...
Data<Bike> bikeData = bike.getFacet(Data.class);
Class<? extends Bike> defaultBikeType =
bikeData.getDefaultComponentType(); ❶
Component<Frame> frame = bike.getPartComponent("frame");
Data<Frame> frameData = frame.getFacet(Data.class);
Attribute<Frame, Double> height = frame.getAttribute("height");
Double defaultHeightValue =
frameData.getDefaultAttributeValue(height); ❷
Component<Wheels> wheels = bike.getPartComponent("wheels");
Data<Wheels> wheelsData = wheels.getFacet(Data.class);
Wheels defaultWheelsValuePartLevel =
bikeData.getDefaultPartValue(wheels); ❸
Wheels defaultWheelsValueComponentLevel =
wheelsData.getDefaultComponentValue(); ❹
3726"!
%4"7
Data5getDefaultComponentType❶%2
!getDefaultAttributeValue(Attribute)
❷%:!25 getDefaultPartValue(Part)
❸%22@Default.Query
5/12""
@Default.Query "%2
getDefaultComponentValue 5
❹%
4A/BData!Domain
&6R92!"0%"%
The Validation Facet
"2 2 !
Validation%4!! *
9R<%R4&
'((
Component<Bike> bike = ...
Validation<Bike> bikeValidation =
bike.getFacet(Validation.class); ❶
// obtain constraints defined on component level
Collection<Constraint<Bike>> componentConstraints =
bikeValidation.getComponentConstraints(); ❷
// obtain constraints defined for a particular attribute
Attribute<Bike, String> label = bike.getAttribute("label");
Collection<Constraint<String>> labelConstraints =
bikeValidation.getAttributeConstraints(label); ❸
// obtain constraints defined for a particular attribute
Part<Bike, Wheels> wheels = bike.getPart("wheels");
Collection<Constraint<Wheels>> wheelsConstraints =
bikeValidation.getPartConstraints(wheels); ❹
// perform validation
bikeValidation.validate(); ❺
// retrieve constraint violations
for (ConstraintViolation violation :
bikeValidation.getViolations()) ❻
{
log.message("Constraint " + violation.getConstraint() +
" on target " + violation.getTarget() +
" is not satisfied.");
}
& 2Validation Component5getFacet(Class)
❶%4Validation
*getComponentConstraintsConstraint
❷%4getAttributeConstraints(Attribute)2
2 ! ❸2 !
getPartConstraints(Part)❹%
4 " . Constraint
2
% 4 Constraint 2
Constraint.validate()%0!2
6"289 5
"" 22!
%8!2!
"2" 6"
Validation5validate❺%
"22"2 getViolations❻%
"622Con-
straintViolationgetTarget2"getConstraint%
4A/BValidation!
ConstraintConstraintViolation&6R92
!"0%"%
5.3.2.5. Working with the Configuration Agenda
4&+2 2!
%89 2
+ 9
'(#
&+%5 Agenda2!2
2ConfigurationSession*
ConfigurationSession<Bike> session =
configurator.createSession(Bike.class);
Agenda<Bike> agenda = session.getAgenda(); ❶
Iterator<Task<Object>> openTasks = agenda.selectItems(
new Filter() ❷
{
public boolean select(Task<?> task)
{
return !(task instanceof CompositeTask) &&
!task.isComplete(); ❸
}
}).iterator();
// simplified configuration process
while (openTasks.hasNext()) { ❹
Task<Object> task = openTasks.next();
Domain<Object> domain = task.getDomain();
if (domain.isEnumerable())
{
Object chosenValue = letUserSelectValue( ❺
task.getDescription(),
domain.getValues());
task.setValue(chosenValue);
}
else if (domain.isBounded())
{
Object enteredValue = letUserEnterValue( ❻
task.getDescription(),
domain.getValueType(),
domain.getLowerBound(),
domain.getUpperBound());
task.setValue(enteredValue);
}
else
{
Object enteredValue = letUserEnterValue( ❼
task.getDescription(),
domain.getValueType());
task.setValue(enteredValue);
}
}
assertTrue(session.getConfiguration().isComplete()); ❽
2!AgendaConfigurationSession❶%E62!
❷AR;%<%$2N& 44"O!B2"
❸ Agenda5 %
42!"" *!
65❹% 5.2!
L❺2
L❻2
L" "❻%
9R<%R4&
'('
4%2!2
❽%
8 2
%46%
5.3.3. Configuration Submission and Further Processing
2!5! 2
2%E!2!
2""""%
0!"89 &+!!
*
ConfigurationSession<Bike> session = ... ❶
// assert configuration validity and completeness
Configuration<Bike> configuration = session.getConfiguration();
assertTrue(configuration.isValid() &&
configuration.isComplete()); ❷
// persist configuration
session.store(id); ❸
// submit configuration for further processing
session.submit(); ❹
// close session
session.close(); ❺
4. 2ConfigurationSession
C❶%E62""2! 2
isValid2 isComplete❷%
true22 5"
2 ❸ ❹%1
7!@Stored"@Submitted2 Configura-
tion"%
4@Submitted Configuration"""6=
/16"*
public class ERPConnector
{
@Inject
private ERP erp;
public void process(
@Observes @Submitted Configuration<Bike> configuration) ❶
{
Bike configuredBike = configuration.getValue(); ❷
erp.order(bike);
...
}
}
62ERPConnector" ❶%
2 " 2 Bike
+ *36 89
'($
6 Configuration5getValue❷%4/1
C2"7
%ERP.order(Bike)%
"2 ConfigurationSession.close()❺%4
close!89 7%
4&+! %5"6
2/1%62!5
2!6 89 5+%
5.4. SPI Usage: Extending and Integrating Open-
Configurator
&R<%'2N&8!O289 "
626"9 %
2!566
!%D5 + %
Example Plugin: the JPA Meta Model Facet
&62!! 26/+&
" ComponentDescriptor%9
!*
Example 5.1. SPI Usage Example
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.persistence.EntityManagerFactory;
import javax.persistence.metamodel.ManagedType;
import configurator.spi.Initialization;
import configurator.spi.metadata.ComponentDescriptorImplementor;
/**
* A plugin that exposes the JPA metamodel of a managed component
* type as a facet of that component.
*/
public class JPAMetaModelFacetPlugin ❶
{
@Inject
private EntityManagerFactory emf; ❷
public <C> void registerFacet(
@Observes @Initialization
ComponentDescriptorImplementor<C> implementor) ❸
{
if (emf == null)
return;
Class<C> componentType = implementor.getComponentType();
ManagedType<C> managedType =
emf.getMetamodel().managedType(componentType); ❹
if (managedType != null)
implementor.addFacet(ManagedType.class, managedType); ❺
}
}
9R<%R4&
'(;
❶4 /25"89
%
❷D 2"C"!8
9 !%62 "
EntityManagerFactory"/+&%
❸1" ComponentDescriptorImplementor . A
R<%'%;2N)31OB2 .
%4""2 6
22!%4C
2!22
" .AR<%'%;2NOB%
❹& /" .2
ManagedType/+&'%
❺4ManagedTypeA"B
.addFacet(Class<F> type, F facet)%E
ManagedType5"89 "
"/"%
& 52
89 2"92" 2!
ComponentDescriptor .%
4! 2!*
Component<JavaBean> component =
session.getConfiguration().getRootComponent();
ComponentDescriptor<JavaBean> descriptor = component.getMetadata();
if (descriptor.hasFacet(ManagedType.class))
{
ManagedType<JavaBean> facet =
descriptor.getFacet(ManagedType.class); ❶
PersistenceType persistenceType = facet.getPersistenceType(); ❷
// ...
}
D ManagedType.class❶%&62!
7"A"222%BJavaBean
❷%
&762!2!"6
.! "%
, 66 +,"6
!23-+9&"2 A
B!%
5.5. Summary
2!89 56
%3"2 "
/12!R;%;2N,
9O2 %
2! "89
%D
!2 *
"
'(<
L /2 &+42
L /+&2
L 12
L9%
+"2!)-"2.-"/
!52!!C6%
&"2!.89 2
%,2!2!
"!%4
."89 *
0 4"
&+2"
%4".2"2
%
0 89 !
!"%4
. !/33 2 /+&21
/&[1%
!"10 !6 !
!"6289 )
%"%4 +"
."9"%
1 0 "289 "
2"
6 +%
4 &+!+2!C
! %D62! !89
*
#% 8 " %
'% +
%
$% %
D2 A 22
2%B". !
&+ ! %&"2!!2 2
&+" "%
"2!6689 !%
629R?2#$2!!
" +%4
2!" 2!22
%
'(?
'(@
6
Evaluation and Validation
2!89 !
!5 2 %
!!".
"%4!2! !
77%
"22!!*
L 6"H1 H
2 #2
L +2
%
D!!2*
L !7! 2
L &+ 2!
%
D!"
%"2!5!6"
.%
6.1. Case Study: Bike Configurator for the iPad
&62!
","1%%
6.1.1. MyCustomBike Inc. - the Custom Bike Company
,"91% !"
2""A!'B%E","
#4"- 562I- '(#(2%'?<J%
'I*==%!% =!=+J2/"#(2'(#'%
9R?%R3
'(F
91%"2"!
." "7%&"
"2!""!2 "2
6 2!%
& 2!6
,"91%
"" %
&"2,"91% " A
!a'(a;(B2!"
2"2 .
%&2 67!
2 !7 2
%
,"91%2!2
" &+
7"%
" H"H2
" 62!"%
,2 256
2!.7
,"91%5%
6.1.2. MyCustomBike Inc.'s Product Range
4 "".2
!." %4 2*
L -
L ,A,41B
L 9"
L 3AB
3""..22 7%1"2
! A R?%#2N9
1OB*
L
L )
L 1
L 9U+
L U0
L D
L U
L ,U1"
L 37
466 2!6
2R1%#2N9O%
41,
'(G
Figure 6.1. Components of a Bike$
6.1.3. The Bike Domain Model
R?%'2N,:9 1,O!
6 %
46R1%'2N9O%
4! 89 *
0
L0 ,Bike@Selectable2
SeatpostSaddle2 StemHandlebar2 Brake2 Gearing2 CranksPedals2 Wheels2
EquipmentMotorBattery%
L 0 4Bike5Frame@Configurable%
80
L@0 &5descriptionprice 22
%
L90 !2 %
L10 4Frame 2"String2
label%
L 0 4weightBike!Frame5size
"%
$4! !"%2*==!!!%"%=%& %
9R?%R3
'#(
Figure 6.2. UML Class Diagram for the Bike Domain Model
$0
L 0 &
@Domain.Query%
L80 4 Frame
@Domain.Query "
"/%
$0
L 0 D65"2
!" %E"2
Bike"A RacingBike2MountainBike2CityBike
ElectroBikeBEquipmentA!"Mudguards2LightCarrierB%02
!77
%
L80
L%* 4 " ! 2 Frame.material2
Frame.color2Brake.type%/"%3
""%
L7*4Gearing.gears6AB
%
L9*4labelFrameAB
%
$0
L5"04!2
6 "%42"
%36MotorBattery.power2MotorBattery.maximumSpeed
LightCarrier7%
4),9 9
'##
L!0 ,6
%& !/"2!"
A% %2Frame.color2Frame.material2SeatpostSaddle.type%B2
6Frame.label%4
@Domain.Query%
LC0 4Frame.label "
"String%
$0
2@Default.Query%
&"2Bike"MountainBikeRacingBike
wheels% Frame2
%
0
L@0 &!@Relational2
%
L@7&60 DBike27"
@Required@Optional%&@Se-
lectable2!
2
"!"%0!2@ConfigurableFrame2@Variable
@Required%
L 2< 930 4 Frame.label !
@javax.validation.constraints.Size6
%
L &"0 4Gearing.gears!
@Min=@Max26"!
"%
10
L$0 &description
@Product.Description%
L1045price@Product.Price%
L80 4Bike.image%
025@Asset%
4!.R?%$2N9 +O2
!!6 %
6.2. The Generic Mobile Configurator Client
1 1 2!!"
+2!!
"%
6.2.1. Technology
+2!
04,:</!!%4
!"2!" "8;
"%"!%4!
!%
;*==!!!%%===2& <2'(#'%
9R?%R3
'#'
4
4%
Vaadin
! "04,:<2"&/&[?
AB6!%2!
"AB/57!
04,:/!%"2
) D4A)D4B@2 "" /
"./2!!%
02 "2"
044+%!!
/! FD4G%+"2
! 2!6
" %8)D45"2!
/2
!! "%
!" %2"
5 !%4
"!/2
5!A-+9B
!%#(
Vaadin Touchkit
,2#@(##2 4
#'2 04,:<&
++%D4!2
!U/2
!/33A"9 "2R<%#%;2
N96"C/33A9BOB%
89 !2 4
!!" /2 &+!
%& /25 "
%,2
"!5!
89 !"
&+2AB"%
:5 2! 89
%
6.2.2. Architecture
4=04,:<
R<%'2N&8!O" "%&
<&%=" 69
?&% !" , ! <,:2 *==%!% =!
=&C6VA+ B2/"#<2'(#'%
@*==% %=!=2/"#<2'(#'%
F*==%!% =!=! VA/B2/"#<2'(#'%
G&%%> 2*==!!!%% =!=2/"#<2'(#'%
#(2!2!
"H1H2*==%==/"#<2'(#'%
##*==%="2/"#<2'(#'%
#'*==%=2/"#<2'(#'%
&
'#$
2;2!! R?%$2N)
,9 &O*
Figure 6.3. Generic Mobile Configurator Architecture
$#0 42!
!89 /+&%D/+&2
,"`:#$%4
22[,:%
:#0 4"89 !%
6 2!"
""%
1#0 $2
!
%4 2!
"%
4." "
%4
!5/C%4
!".
" !%
4"!9 &+%
#04!"!)
D4A)D4B%2!
!!.! "
"%,2
. 04,:<28,#;9#</%
#$*==!!!%"7%2/"#?2'(#'%
#;&%-C
#<&% %"%
9R?%R3
'#;
42!"/
6"/33?D+!2
/1&@%##?%4!"04,:<
!!2!""%
6.2.3. User Interface
0 52!!!
% R?%;2N,
9 DO " *
Figure 6.4. Mobile Configurator Wireframe
❶80 4! !
2 *
L40+ " %
&!%
L<%04! %
4! !%
L 0 4
%! 2!5"%
L 04 ! %
%4 7
"%
L0 4 " %
#?*==!!!%C% =C2/"#?2'(#'%
'#<
❷0 4" %
!! 2"
" %
❸ 80 4!
%! "
2 %,2
!!2!2
%&2!"
5AgendaCAR<%$%'%<2ND !9
& OB%
Figure 6.5. Hierarchical Agenda Navigation
4 %42
! . *2
2 "%3
!5%
R?%<2N0& E O
%
❹'<0 42! !2
* 2
!6="%"2
%2"!
%&62!
"%
❺$0 4 "
%4 !
5%
%
❻90 & 2.
!" %D
..2 2
5!@Product.Asset2!
%
9R?%R3
'#?
❼ 0 4!
%2""
%,2
A -2
R$%$%'%'2N=-OB%"2
2!!
2 2!
!
%
R?%?2N36")9 O!6"
%
Figure 6.6. Exemplary Screenshot of the Generic Configurator
6.3. Configuration Procedures
D"!!6 !1
%D! 2!!!*
L 9 ! "
L 9
L 4
L !
L & 7
L
9 E!19
'#@
6.3.1. Creating a New Bike Configuration
4 "!% R?%@2N9
9 E!9 O! %
! H&H❶%
5! 22
@Configurable @Product2!!
%0!2Bike""
2!ConfigurationSession%
DConfigurationSessionCConfiguration
%2
"%"2Agenda!
2 " %4
!!AgendaC❷
22Bike5"❸%
Figure 6.7. Initial Configurator State after Creating a New Configuration
4Electro Bike"❹% R?%F2N9
4"O!%
E!2"2
" /1 bike.getWeight2
bike.getImagebike.getPrice%02"
" "*
L! !❶2
L ❷2
L"❸%
9R?%R3
'#F
&H,U1"H ❹%
ElectroBikeMotorBattery""%4
6Bike"A R?%'2N,:9
1,OB%
Figure 6.8. Configuration State after Type Selection
9 19
'#G
6.3.2. Configuring the Bike Frame Component
R?%G2N 9O!
Frame2!@Configurable%D
!"2!
❶HH6%
4!5"
2!!❷%E
"" 2 ❸%
Figure 6.9. Specification Dialog of the Frame Component
9R?%R3
''(
6.3.3. Triggering and Resolving a Configuration Error
:5Frame5label*
26 ';A"
@Size(max=24)"5 B%4
2!"%
R?%#(2N.9O"
*
Figure 6.10. Visualization of Constraint Violations
4"❶! ❷ !
"A6B%2 "
❸%&"
6 " "
❹%4 "%
D
''#
6.3.4. Selecting Wheels
4Wheels6!@Se-
lectable% 2
5%
R?%##2ND O! SelectCom-
ponentTask*
Figure 6.11. Wheels Selection Dialog
4 2Wheels! 2"
❶%
4Wheels❷%9"2
!5wheels❸%42wheels
" " %
9R?%R3
'''
6.3.5. Adding an Equipment
E62!!!2!25equipment2
! %
R?%#'2N++O!57
*
Figure 6.12. Plural Part Specification
2H+H7❶%4
75SpecifyPartQuantityTask%4"
7 ".
"❷%&7"!6Equipment❸%
! Equipment"2"Mudguards2
LightCarrier2""!"7
❹%& Mudguards2 SelectCom-
ponentTaskMudguards❺%
&2!7"
%
9
''$
6.3.6. Submission and Checkout
E!272
" %
R?%#$2N9 O!!
%
Figure 6.13. Configuration Submission
& H&H ❶2 2
" !! ❷%&
2"*
L 2
L ! +#@2
L 6 [,:2
L %
& H&H❸2
2!
❹% !2"
%
4 ! %! 2!5
" %
#@&%-4
9R?%R3
'';
6.4. Validation
89 5 !2
%&2!!
+%D5
! %
6 D%
0 2!5!2
"89 ! %& 2
"."C
%
2"/! !"
/+&/&[1"7%2
!2""""
C26/%
@ ( "0 ,2
89 !"6
" 65"%42
" " %2
!2"" %
@0 &.
"/12 !
C2! 6"
% 2 !
7C!
%D289 !"
" 2"2
6 %
&"2!
%E2"!2
A3B".2! !
2 "6 2 2
2 2,: !
%&2 5" /2
! A9,B"
#F)#G%4! 6 !
! "C""%
810 4
!"289
!&+ %
2!!2
2 "
.%
"2! 89 "!
!72 %3
2!!7
%
#F*==%% 2/"#G2'(#'%
#G*== %2/"#G2'(#'%
"
''<
6.5. Summary
2! ""89 !
"%4" .
","91%%
&" 6" ,"91%52
!"5 2!!7" ,:
%4/A&6R12#)-63B
"2!2!9R;2
2.%4"2
!"89 %
E62! 2!
%& 04,:29/!
2 &5+
"%D. 2
"2!!!"!
R<%'2N&8!O%4" 5
"%
42!! 6 %
4 !"
%
"2!."2!
!2
C%
622!!!
%
''?
''@
7
Summary and Outlook
42!!!"
7%,2!!".
! "%
1 !Q2!!
2 C!%
7.1. Discussion
2!!" ."%
62!!6! 7*
L0 89
!!.7"P
L0 0!P
:5 " 7%
7.1.1. Methodology Suitability
R'%#%$2N9.++9 O!
. % 1 2
! ! "2
. % & 2 ! ! 2 !
89 5 ."%
22"2
2.!89 !*
0 &2!
"%.2"
9R@%R"8
''F
@Selectable% 2
""
2"" %
0 +.!%
.2@Configurable2
!""@Configured@Variable@Parameter
%4.6A2B
@Domain6!%
0 & " . @Con-
structible"%& ""
"2
5%
.%02"@Parameter
%
.2"2
2 C22
.%
42R'%#%$%#2N9.&O2
6!*
Example 7.1. Modeling Customizable Products with OpenConfigurator Concepts
@Configurable
@Product
@Domain.Query
public class CustomizableProduct ❶
{
private FixedArea regularPart; ❷
private String regularAttribute; ❸
@Required
@Configured
private ObligatoryElement constrainedConfiguredPart; ❹
@Optional
@Variable
private OptionalElement variableAttribute; ❺
@Parameter
@Max(100)
private int parametricAttribute; ❻
@Configured
@TypeDomain({ SolutionA.class, SolutionB.class })
private Principle configuredAbstractTypedPart; ❼
@Configured
private Service configuredPart; ❽
@Configured
private Shape constructiblePart; ❾
// ... getters & setters
}
, ""
''G
@Selectable
public abstract class Principle { ... }
public class SolutionA extends Principle { ... }
public class SolutionB extends Principle { ... }
@Constructible
public class Shape
{
@Configured
private Collection<Vertex> vertices;
// ... getters & setters
}
@Configured
public class Vertex
{
@Parameter
@Max(1000)
private int x, y;
// ... getters & setters
}
0 &"❶%89
%4.AB
"AB""
!@Product%
5"0 & 2❷❸2
%4"
6"%
60 & 2"
2"@Required❹@Optional❺%
0 96 2 @Parame-
ter❻%,"25"
%
10 & C
.%4
❼%022!=6
"2%,!"2
"%4"22
!"%
0 & @Configured%
$"0 96!@Constructible
%
%42 ❾%4"
Shape2! @Constructible%4
2!%
!"2
!2 %
9R@%R"8
'$(
"0 1"2)6
%8!"6
%4289 5"%
"289 2.
%
4!2 2.
89 5%
7.1.2. Implementation Characterization
R$%$%$2N9 .O2!6"
. %489
2! 2!!.!
%
R@%#2N989 !, 169
O! 6 89 5
6%E!""
9R?2#$
.%
8"0 - )289 5
!"1'11'9
% 6"2
6"% 2
2! "
. 2"62
6AB"%,2 2
!62
6%-
2!"2
""%-"
2!!89 " "
!%
0 -289
!.!* 2!"
2! %0!22
!2 .%!
22" .%4
2!!2
!&++ 2!
%4" 2
! 04,:<2!!
! !!2A !U
B%D".2 "
%
9.
'$#
Figure 7.1. Classification of OpenConfigurator
within the Morphological Box for Configurators
9R@%R"8
'$'
0 &!R@%#%#2N, ""O2
2.89
%! !"
"%- 2
*
7"I>
.'(##J%,22
%E289 5!""
"" " ! 2!"
I>.'(##J%62
"7!
%4 "%4!
! C" %D22
89 5%
0 E62!5
"89 2 !*"2!
"2 2!
6"% 2
89 5!"
2!"!6.!
.%
,2! """
. "" A"
2 B%
- 289 A""B
22 *
2!! 7"
"2 %2
.2
%42!2
!%4"
".622
!7
% 25 !5&+
2! %
4."89 6
"* 2A7B2A
7B6 %
2!
%
- "289 ""
"%-"2!
*!25
5%0!2"2
2"
6%02"2
%
"
!AR@%'2N8OB%:
" 62
%0!2!
""" %4!"25
D
'$$
"
"%
89 "
%4C!!%E2!
2!22"
.%
-289 62
%4 ."
"2!"@Product.Asset
" %25"
!!"
%42!
""2*"
2!@Product.Price%
0 "2!
%9"2H89 !H"2
.=!%,2
89 "
%- 2!
.22 "C2
"7%D""
2 5"
!%&2 C
!AR@%'2N8OB%
4. "! 6
!"89
%,2"!%
D!!R@%'2N8O2"
7
89 !%
7.1.3. Strengths and Weaknesses
"2!!" !89
"%D5 !
6!%!!!
*
0 "8
9 %
#0 . !
"%
0 !" "
%
8 !*2!
7%
9R@%R"8
'$;
7.1.3.1. Strengths
D "*
Conceptualization
C A 0 "2H3" /H*"
/ 2 "
2 "%4!!
!!6 / %
8C 2/22/33 /+&2
91"!2.%
4 "789
! "%
A0 4"
%4"C
/5 ""!%
4%D2 ,:
""2
"2 %
E2 ".
!66 ! 5
!"%D
""%
=A0 D
2 "
* !
"22 %
,2 ! 2
! 22
"%4!
2""
%
47 ""
"%
10 8.C2
"! " !"2
"!%,2!
! !6AR;%;%;%#2N
OB%D !".
7"6
C576"%
&2 "
!2%& 2"
22!
%
Technical
40 , !!C
%2!
"2 !
D
'$<
2! "%&6
9R?2#$!%
4 " "
2"2 6 "%
$0 ,2! 2 2
"%/ "2
3#%4!
2 2 /%
" 89 /2.
2%62! /'
" " 35
! %4289 !
"52!"
%4!%
D89 27"5"
!%4"!%"2
"2"C
!"%
Implementation
C0 489 ! %42
"%32!
5"%4
!/2"
"%
97"289 ! "
2! "2!
C%
5"A"0 2!
2"9$2! "62"
"%
D ".!
"6 %422
"%
$0 "2! 89 5"
&+"""
56"%
D2!"6
/6"%2!
!%
#&%" -#
'*==!!!%C% =2/"''2'(#'%
$&%6-""C2R<%#%;2N96"C/33
A9BO%
9R@%R"8
'$?
7.1.3.2. Weaknesses
& 89 5 "
2" 2
!%D!6
7! %
Conceptualization
40 1 C"7
!
5C* %D
89 52
"2 !
" H H
%
2! "2%4"2
"6 2 %
!2! 2!
2% %2
!%
@%0 &" "
2!"
%8 2
2 2! %
D!" "2 H H
AB2! !"
%62!
" 2"
"HHHH%42
! 2" [,:2
89 !%
Technical
80 8 "!
/%D2!"2
89 !26
" ! 6%42
"2 DXDX);
"2"%2!
%
E2! 2
2"2!6%46
" ! 2"
2 %,2!2"
" 2
6%& ""8
9 2"
"" A9B"2"
7%
:%0 489
"722!
;&%>?%">?1
8
'$@
* ""
%2"%
0!2! *2"
""7%4!"
!%2 5!
""2
% 2% %2
"!"=%D2
2
!%
Implementation
10 +"89 25
"" *"%D
.25"%! 6
" *
L0 4 ."%2
"%&2.
"%
L0 &
%
L0 622
H"H5
"%
L'&0 9"289
5 29+<"
%42 5"
"%
+"22"! 2
7"2 ?%D
"
2 %1"
2"%
D! R@%'2
N8O%
)6 2! "
! !"%4 2!
"%"2"!
C"! %
7.2. Outlook
"2!!89
!%D!!
2" %
289
%D
. %
<&%%
?R$%$%$%;2N9 9O2H8"="H%
9R@%R"8
'$F
4 !2!!*
50 R$%$%'2NO2! 62!
%D" 9
R?2#$2"2"
"5"%42 7
2689 !
"%
0 ,2R$%$%$2N9 .O2!6
6 %R@%#%'2N
9.O2!.!
%4.!!5
%
D2! 2
!*
L 1& 0 &"R@%#%$%'2ND
O2C 9+
2!!"
%D! R@%'%#2N9+=9
O%
L@0 " 2.
!
!%5""5 "
2!!"7 A+B
%D! 2
"- I- '(#(J2R@%'%'2N-
O%
L90 &6 "
.%3" 2
" "
I-'(#(J%
:5!%
7.2.1. CSP/Constraint Solver Integration
9 A9+B
A&B% A9+B
"!"@%49+
!C"
C"F%
&.%/".$*-*/2!$
2-!%
&%&
5 5"
%
4 2
%4 9+A
@22I>#GG'J2I1b'((<J%
FI#GG@J2I#GGFJ2I/#GGGJ2I#GGGJ2I '((#J2I/'(('J2I&'(('J2I:'((<J2
I!'(##J%
-
'$G
I-'((?2%<(JB%4"7 !"
9+2 AI4'((GJB%
1"2 9+"!*!
2!
%4""
%
0!2" ! AB
9+62A*I '((#J2I1!'((FJB*
L#0 2
!9+%
L#0 2
""" 5
%
D9+62%
%.%%/IE"#GGGJ-%
.-%/G62
6%
& "
"-I-'((?J%-"
2"
%
89 " !
%0!25!
""%262
!"/9+H/-$$#*9+ &+H#(2!
!!%4!"2
%,2
289 !"
26
/"%
7.2.2. Recommendation Integration
2- 2"
2!"2
" "I- '(#(J%
.##72-
"
" " %4
6 AH
H#'B
A%I'((?2%;<;@JB%&"26"
!
%&"7%
D""2!
!""!A"2
G *==%!% =!=9VV]"V9+2 /" '$2
'(#'%
#(*==C% ==C=PW$$#2/"'$2'(#'%
##H.HI'((?2%#'J%
#'%I4#GG;2%;FJ
9R@%R"8
';(
&.%#$B2 "
!%42 - 2"
!6"*2 7
""7 "%
12- 6
2 62
" !%4
"7
" %36*
L " 2!5
2
L 2"2
L . 2! 2% %2
5%
(2
2 26"
%- 6
28B#;2 !
2%
489 !" "
%D 2
"!27
- 5!A%I- '(#(2%F(2#<(#<'JB -9>
%,2!289 !!"
"%4" - 5
C%
7.3. Conclusion
+ ! 2
2 .%4 2 "
6!!
%
4 "
2 ". "%4
! .
!2! 6
%4 H89 H%
4 2!"..2!
62! A9R'2
B%,2!
2A9R$2B%4
72" "%
4 "9R;2
2.C%
2
%4 C2!2
2%
#$*==!!!%.%=2&'<2'(#'%
#;"8B
9
';#
.2!*
#% 9.C
%
'% !2
"2"2 57%
97"2.2!
6
%
42./2!/
2 2 *
L +AB
L +AB
L +9."A B
L +AB
L +-AB
1!9R$22!
!569R<2
!"%4 !
%4"2
2 2!
%1 2
&+.26 *
A /+& "B
A 1B%
D"29R?2#$2!!
!.!"
.%
D289 " "
. 2 "2"6
"!"%32" !"
"2 "%
489 !A"B
! %"2!
2
*!5!22
" %89
6"2."6"%
';'
';$
A
Constraints
4"89 6! %
&6R&%R9
';;
Table A.1. Logical/Arithmetical Comparison Constraints
8
@23 $ !"
@Equals a.equals(b) a7b%@Equals(value="#{_this.b}",
condition="#{_this.unicolor}")
Color a;
Color b;
boolean unicolor;
@NotEquals not a.equals(b) a7b%@NotEquals("#{_this.b}")
Color a;
Color b;
@Min a >= b a7
b%
@Min("#{_this.b}")
int a;
int b;
@Max a =< b a7
b%
@Max("10")
int a;
';<
Table A.2. Cardinality Constraints
8 @23 $ !"
@Cardinality |a| == b .a7b%@Cardinality(5)
Collection<Item> items;
@Cardinality.Min |a| >= b .a7
b%
@Cardinality.Min(1)
Collection<Item> items;
@Cardinality.Max |a| =< b .a7
b%
@Cardinality.Max("#{_this.available}")
Collection<Item> items;
int available;
@Optional |a| >= 0 3"2
""
%
E"2
!!"
""%
@Optional
Collection<Equipment> equipment;
@Required |a| >= 12%%a != null 32"
%
@Required
Frame frame;
&6R&%R9
';?
Table A.3. Compatibility Constraints
8 @2
3
$ !"
@Compatible.Type typeOf(a) = b 4"b "
a%
!2a5"b
"%
,!
6%
❶8" CompatiblePart
% Part
IncompatiblePart%
class Part { ... }
class CompatiblePart extends Part { ... }
class IncompatiblePart extends Part { ... }
class Product
{
@Compatible
.Type(CompatiblePart.class) ❶
Part part;
}
@Compatible.
ElementType all e in a:
typeOf(e) = b ea2"b
"e%
!2ea"b
"%
,!
6%
❶8" CompatiblePart
%Part
IncompatiblePart%
class Part { ... }
class CompatiblePart extends Part { ... }
class IncompatiblePart extends Part { ... }
class Product
{
@Compatible
.ElementType(CompatiblePart.class) ❶
Collection<Part> parts;
}
';@
8 @2
3
$ !"
@Compatible. Matches condition(a) =
true acondition%a
H_Hcondition%
❶MatchingPart
%
NotMatchingPart
%
class Part {
abstract boolean matches(); }
class MatchingPart extends Part {
boolean matches() { return true; } }
class NotMatchingPart extends Part {
boolean matches() { return false; } }
class Product
{
@Compatible.Matches("#{_.matches()}") ❶
Part part;
}
...
@Compatible.
ElementMatches all e in a:
condition(e) =
true
ea2
econdition%4
e
H_currentHcondition%4
aH_H%
❶MatchingPart
%
NotMatchingPart
%
...
class Product
{
@Compatible
.ElementMatches("#{_.matches()}") ❶
Collection<Part> parts;
}
&6R&%R9
';F
Table A.4. Incompatibility Constraints
8 @2
3
$ !"
@Incomaptible.
TypeNot typeOf(a) not b 4"b "
a%
!2a5"b"
"%
,!
6%
class Part { abstract boolean matches(); }
class MatchingPart extends Part {
boolean matches() { return true; } }
class IncompatiblePart extends Part {
boolean matches() { return false; } }
class Product {
@Incompatible.TypeNot(IncompatiblePart.class)
Part part;
}
@Incompatible.
ElementTypeNot all e in a:
typeOf(e) not b ea2"b
"e%
!2ea
"b""%
,!
6%
class Product {
@Incompatible
.ElementTypeNot(
IncompatiblePart.class)
Collection<Part> parts;
}
@Incompatible.
MatchesNot not condition(a)
= true acondition%
aH_H
condition%
class Product {
@Incompatible
.MatchesNot(
"#{_.matches()}")
Part part;
}
@Incompatible.
ElementMatchesNot all e in a: not
condition(e) =
true
ea2
econdition%4
e
H_currentHcondition%4
aH_H
class Product {
@Incompatible
.ElementMatchesNot(
"#{_.matches()}")
Collection<Part> parts;
}
';G
Table A.5. Complex Constraints
8 @23 $ !"
@Satisfies eval(script) = true 1%&
value
true%
@Satisfies("#{_this.x < _this.y}")
class Product {
int x;
int y;
}
@Relational exists(a, R) 1%&
aR%
@Selectable
@Relational
@Domain.Query
class Product {
int x;
int y;
}
'<(
'<#
B
Example Domain Model: Bike
B.1. Component Specifications
46#6
9R?2#$%
#4"""%2*==!!!%"%=2
/"#F2'(#'%
&6R1%R36,*1
'<'
9
'<$
B.2. Source Code
Class Bike
package example;
import java.math.BigDecimal;
import java.util.Collection;
import configurator.configuration.annotation.Calculated;
import configurator.configuration.annotation.Configurable;
import configurator.product.annotation.Product;
import configurator.product.annotation.Product.Asset;
import configurator.product.annotation.Product.Attribute;
import configurator.product.annotation.Product.Price;
import configurator.validation.annotation.Optional;
import configurator.validation.annotation.Required;
@Configurable
@Product
public abstract class Bike
{
private Frame frame;
private Gearing gearing;
private Brake brake;
private CranksPedals cranksPedals;
private StemHandlebar stemHandlebar;
private Wheels wheels;
private SeatpostSaddle seatpostSaddle;
private Collection<Equipment> equipment;
private int weight;
private byte[] image;
private BigDecimal price;
@Required
public Frame getFrame()
{
return frame;
}
public void setFrame(Frame frame)
{
this.frame = frame;
}
@Required
public Gearing getGearing()
{
return gearing;
}
public void setGearing(Gearing gearing)
{
this.gearing = gearing;
}
@Required
public Brake getBrake()
{
return brake;
}
&6R1%R36,*1
'<;
public void setBrake(Brake brake)
{
this.brake = brake;
}
@Required
public CranksPedals getCranksPedals()
{
return cranksPedals;
}
public void setCranksPedals(CranksPedals cranksPedals)
{
this.cranksPedals = cranksPedals;
}
@Required
public StemHandlebar getStemHandlebar()
{
return stemHandlebar;
}
public void setStemHandlebar(StemHandlebar stemHandlebar)
{
this.stemHandlebar = stemHandlebar;
}
@Required
public Wheels getWheels()
{
return wheels;
}
public void setWheels(Wheels wheels)
{
this.wheels = wheels;
}
@Required
public SeatpostSaddle getSeatpostSaddle()
{
return seatpostSaddle;
}
public void setSeatpostSaddle(SeatpostSaddle seatpostSaddle)
{
this.seatpostSaddle = seatpostSaddle;
}
@Optional
public Collection<Equipment> getEquipment()
{
return equipment;
}
public void setEquipment(Collection<Equipment> equipment)
{
this.equipment = equipment;
}
@Calculated
@Product.Attribute(level = Attribute.STANDARD)
public int getWeight()
9
'<<
{
return weight;
}
@Asset
public byte[] getImage()
{
return image;
}
@Price
public BigDecimal getPrice()
{
return price;
}
}
Class Brake
package example;
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import configurator.configuration.annotation.Selectable;
import configurator.configuration.annotation.Variable;
import configurator.data.annotation.Default;
import configurator.data.annotation.Domain;
import configurator.model.annotation.Ignore;
import configurator.product.annotation.Product.Description;
import configurator.product.annotation.Product.Price;
import configurator.validation.annotation.Relational;
@Relational
@Domain.Query
@Default.Query("select b from Brake b where b.type = 'V_BRAKE'")
@Selectable
@Entity
public class Brake
{
public static enum Type
{
V_BRAKE,
DISC_BRAKE
}
private long id;
private String description;
private Brake.Type type;
private BigDecimal price;
@Ignore
@Id
@GeneratedValue
public long getId()
{
return id;
}
&6R1%R36,*1
'<?
@Description
public String getDescription()
{
return description;
}
@Variable
public Brake.Type getType()
{
return type;
}
public void setType(Brake.Type type)
{
this.type = type;
}
@Price
public BigDecimal getPrice()
{
return price;
}
}
Class Carrier
package example;
public class Carrier extends Equipment
{
}
Class CityBike
package example;
import configurator.configuration.annotation.Configurable;
import configurator.product.annotation.Product;
@Configurable
@Product
@Product.Name("City Bike")
public class CityBike extends Bike
{
}
Class CranksPedals
package example;
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import configurator.configuration.annotation.Selectable;
import configurator.configuration.annotation.Variable;
import configurator.data.annotation.Default;
import configurator.data.annotation.Domain;
import configurator.model.annotation.Ignore;
9
'<@
import configurator.product.annotation.Product.Description;
import configurator.product.annotation.Product.Price;
import configurator.validation.annotation.Relational;
@Relational
@Domain.Query
@Default.Query("select c from CranksPedals c where c.type = 'Regular'")
@Selectable
@Entity
public class CranksPedals
{
public static enum Type
{
Classic,
Regular,
Deluxe
}
private long id;
private String description;
private CranksPedals.Type type;
private BigDecimal price;
@Ignore
@Id
@GeneratedValue
public long getId()
{
return id;
}
@Description
public String getDescription()
{
return description;
}
@Variable
public CranksPedals.Type getType()
{
return type;
}
public void setType(CranksPedals.Type type)
{
this.type = type;
}
@Price
public BigDecimal getPrice()
{
return price;
}
}
Class ElectroBike
package example;
import configurator.configuration.annotation.Configurable;
import configurator.product.annotation.Product;
import configurator.validation.annotation.Required;
&6R1%R36,*1
'<F
@Configurable
@Product
@Product.Name("Electro Bike")
public class ElectroBike extends CityBike
{
private MotorBattery motorBattery;
@Required
public MotorBattery getMotorBattery()
{
return motorBattery;
}
public void setMotorBattery(MotorBattery motorBattery)
{
this.motorBattery = motorBattery;
}
}
Class Equipment
package example;
import java.math.BigDecimal;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.MappedSuperclass;
import configurator.configuration.annotation.Selectable;
import configurator.data.annotation.Domain;
import configurator.model.annotation.Ignore;
import configurator.product.annotation.Product.Description;
import configurator.product.annotation.Product.Price;
import configurator.validation.annotation.Relational;
@Relational
@Domain.Query
@Selectable
@MappedSuperclass
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Equipment
{
private long id;
private String description;
private BigDecimal price;
@Ignore
@Id
@GeneratedValue
public long getId()
{
return id;
}
@Description
public String getDescription()
{
return description;
9
'<G
}
@Price
public BigDecimal getPrice()
{
return price;
}
}
Class Frame
package example;
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Transient;
import javax.validation.constraints.Size;
import configurator.configuration.annotation.Calculated;
import configurator.configuration.annotation.Configurable;
import configurator.configuration.annotation.Parameter;
import configurator.configuration.annotation.Variable;
import configurator.data.annotation.Default;
import configurator.data.annotation.Domain;
import configurator.model.annotation.Ignore;
import configurator.product.annotation.Product.Description;
import configurator.product.annotation.Product.Price;
import configurator.validation.annotation.Optional;
import configurator.validation.annotation.Relational;
import configurator.validation.annotation.Required;
@Relational(properties = { "description", "material", "price" })
@Domain.Query
@Configurable
@Entity
public class Frame
{
public static enum Material
{
Titanium,
Aluminum
}
public static enum Color
{
Gold,
Silver,
Black,
White,
Red,
Blue
}
public static enum Geometry
{
XS(16),
S(18),
M(20),
&6R1%R36,*1
'?(
L(22);
private int size;
private Geometry(int size)
{
this.size = size;
}
public int getSize()
{
return size;
}
}
private long id;
private String description;
private Frame.Material material;
private Frame.Color color;
private Frame.Geometry geometry;
private String label;
private BigDecimal price;
@Ignore
@Id
@GeneratedValue
public long getId()
{
return id;
}
@Description
public String getDescription()
{
return description;
}
@Required
@Variable
@Default("Aluminum")
public Frame.Material getMaterial()
{
return material;
}
public void setMaterial(Frame.Material material)
{
this.material = material;
}
@Transient
@Required
@Variable
@Default("Black")
public Frame.Color getColor()
{
return color;
}
public void setColor(Frame.Color color)
{
this.color = color;
}
9
'?#
@Transient
@Required
@Variable
@Default("M")
public Frame.Geometry getGeometry()
{
return geometry;
}
public void setGeometry(Frame.Geometry geometry)
{
this.geometry = geometry;
}
@Transient
@Size(max = 24)
@Calculated
public int getSize()
{
if (geometry != null)
return geometry.size;
return 0;
}
@Transient
@Optional
@Parameter
@Default("MyBike")
public String getLabel()
{
return label;
}
public void setLabel(String label)
{
this.label = label;
}
@Price
public BigDecimal getPrice()
{
return price;
}
}
Class Gearing
package example;
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import configurator.configuration.annotation.Selectable;
import configurator.configuration.annotation.Variable;
import configurator.data.annotation.Default;
import configurator.data.annotation.Domain;
import configurator.model.annotation.Ignore;
&6R1%R36,*1
'?'
import configurator.product.annotation.Product.Description;
import configurator.product.annotation.Product.Price;
import configurator.validation.annotation.Max;
import configurator.validation.annotation.Min;
import configurator.validation.annotation.Relational;
@Relational
@Domain.Query
@Default.Query("select g from Gearing g where g.type = 'HubGear' and g.gears = 7")
@Selectable
@Entity
public class Gearing
{
public static enum Type
{
SingleSpeed,
HubGear
}
private long id;
private String description;
private Gearing.Type type;
private int gears;
private BigDecimal price;
@Ignore
@Id
@GeneratedValue
public long getId()
{
return id;
}
@Description
public String getDescription()
{
return description;
}
@Variable
public Gearing.Type getType()
{
return type;
}
public void setType(Gearing.Type type)
{
this.type = type;
}
@Max(value = "1", condition="#{_this.type == 'SingleSpeed'}")
@Min(value = "2", condition="#{_this.type == 'HubGear'}")
@Variable
public int getGears()
{
return gears;
}
public void setGears(int gears)
{
this.gears = gears;
}
9
'?$
@Price
public BigDecimal getPrice()
{
return price;
}
}
Class Light
package example;
public class Light extends Equipment
{
}
Class MotorBattery
package example;
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import configurator.configuration.annotation.Selectable;
import configurator.configuration.annotation.Variable;
import configurator.data.annotation.Domain;
import configurator.model.annotation.Ignore;
import configurator.product.annotation.Product.Description;
import configurator.product.annotation.Product.Price;
import configurator.validation.annotation.Relational;
@Relational
@Domain.Query
@Selectable
@Entity
public class MotorBattery
{
private long id;
private String description;
private int power;
private String battery;
private int maximumSpeed;
private String range;
private int weight;
private BigDecimal price;
@Ignore
@Id
@GeneratedValue
public long getId()
{
return id;
}
@Description
public String getDescription()
{
return description;
}
&6R1%R36,*1
'?;
@Variable
public int getPower()
{
return power;
}
public void setPower(int power)
{
this.power = power;
}
@Variable
public String getBattery()
{
return battery;
}
public void setBattery(String battery)
{
this.battery = battery;
}
@Variable
public int getMaximumSpeed()
{
return maximumSpeed;
}
public void setMaximumSpeed(int maximumSpeed)
{
this.maximumSpeed = maximumSpeed;
}
@Variable
public String getRange()
{
return range;
}
public void setRange(String range)
{
this.range = range;
}
public int getWeight()
{
return weight;
}
public void setWeight(int weight)
{
this.weight = weight;
}
@Price
public BigDecimal getPrice()
{
return price;
}
}
9
'?<
Class MountainBike
package example;
import configurator.configuration.annotation.Configurable;
import configurator.data.annotation.Default;
import configurator.product.annotation.Product;
@Configurable
@Product
@Product.Name("Mountain Bike")
public class MountainBike extends Bike
{
@Default.Query("select w from Wheels w where w.type = 'Cross'")
public Wheels getWheels()
{
return super.getWheels();
}
}
Class Mudguards
package example;
public class Mudguards extends Equipment
{
}
Class RacingBike
package example;
import configurator.data.annotation.Default;
import configurator.product.annotation.Product;
@Product.Name("Racing Bike")
public class RacingBike extends Bike
{
@Default.Query("select w from Wheels w where w.type = 'Race'")
public Wheels getWheels()
{
return super.getWheels();
}
}
Class SeatpostSaddle
package example;
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import configurator.configuration.annotation.Selectable;
import configurator.configuration.annotation.Variable;
import configurator.data.annotation.Default;
import configurator.data.annotation.Domain;
import configurator.model.annotation.Ignore;
import configurator.product.annotation.Product.Description;
import configurator.product.annotation.Product.Price;
&6R1%R36,*1
'??
import configurator.validation.annotation.Relational;
@Relational
@Domain.Query
@Default.Query("select s from SeatpostSaddle s " +
"where s.type = 'Regular' and s.color = 'Black'")
@Selectable
@Entity
public class SeatpostSaddle
{
public static enum Type
{
Regular,
Trekking,
Race
}
public static enum Color
{
Brown,
Black
}
private long id;
private String description;
private Type type;
private String material;
private Color color;
private BigDecimal price;
@Ignore
@Id
@GeneratedValue
public long getId()
{
return id;
}
@Description
public String getDescription()
{
return description;
}
@Variable
public SeatpostSaddle.Type getType()
{
return type;
}
public void setType(SeatpostSaddle.Type type)
{
this.type = type;
}
@Variable
public String getMaterial()
{
return material;
}
public void setMaterial(String material)
{
9
'?@
this.material = material;
}
@Variable
public Color getColor()
{
return color;
}
public void setColor(Color color)
{
this.color = color;
}
@Price
public BigDecimal getPrice()
{
return price;
}
}
Class StemHandlebar
package example;
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import configurator.configuration.annotation.Selectable;
import configurator.configuration.annotation.Variable;
import configurator.data.annotation.Default;
import configurator.data.annotation.Domain;
import configurator.model.annotation.Ignore;
import configurator.product.annotation.Product.Description;
import configurator.product.annotation.Product.Price;
import configurator.validation.annotation.Relational;
@Relational
@Domain.Query
@Default.Query("select s from StemHandlebar s where s.type = 'Regular'")
@Selectable
@Entity
public class StemHandlebar
{
public static enum Type
{
Classic,
Regular,
Sportive
}
private long id;
private String description;
private Type type;
private BigDecimal price;
@Ignore
@Id
@GeneratedValue
&6R1%R36,*1
'?F
public long getId()
{
return id;
}
@Description
public String getDescription()
{
return description;
}
@Variable
public StemHandlebar.Type getType()
{
return type;
}
public void setType(StemHandlebar.Type type)
{
this.type = type;
}
@Price
public BigDecimal getPrice()
{
return price;
}
}
Class Wheels
package example;
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import configurator.configuration.annotation.Selectable;
import configurator.configuration.annotation.Variable;
import configurator.data.annotation.Default;
import configurator.data.annotation.Domain;
import configurator.model.annotation.Ignore;
import configurator.product.annotation.Product.Description;
import configurator.product.annotation.Product.Price;
import configurator.validation.annotation.Relational;
@Relational
@Domain.Query
@Default.Query("select w from Wheels w where w.type = 'Urban'")
@Selectable
@Entity
public class Wheels
{
public static enum Type
{
Urban,
Cross,
Race
}
private long id;
9
'?G
private String description;
private Type type;
private BigDecimal price;
@Ignore
@Id
@GeneratedValue
public long getId()
{
return id;
}
@Description
public String getDescription()
{
return description;
}
@Variable
public Wheels.Type getType()
{
return type;
}
public void setType(Wheels.Type type)
{
this.type = type;
}
@Price
public BigDecimal getPrice()
{
return price;
}
}
'@(
'@#
C
OpenConfigurator API/SPI
Interface OpenConfigurator
package configurator;
public interface OpenConfigurator
{
/**
* TODO emit BootstrapImplementor event TODO emit
* ConfiguratorImplementor event
*/
public Configurator initialize();
}
Interface Bootstrap
package configurator.bootstrap;
import configurator.Configurator;
import configurator.spi.Initialization;
/**
* Bootstraps the configurator instance. The bootstrap sequence:
* <ol>
* <li>invoke {@link #initialize()}</li>
* <li>obtain {@link Configurator} instance by calling
* {@link #getConfigurator()}</li>
* </ol>
*/
public interface Bootstrap
{
/**
* Triggers initialization of a configurator instance. Emits a
* {@link Configurator} {@link Initialization} event.
*/
void initialize() throws BootstrapException;
/**
&6R9%R89 &+=+
'@'
* Obtain the initialized configurator instance.
*/
Configurator getConfigurator();
}
Interface Configurator
package configurator;
import configurator.model.Configuration;
/**
* The main entry point to the configurator API. Allows to create
* configuration sessions. TODO emit events: @Preparation
* ConfigurationSessionImplementor, @Preparation
* Component/Attribute/Part, @Initialization Component/Attribute/Part,
* @Initialization ConfigurationSessionImplementor
*/
public interface Configurator
{
<T> ConfigurationSession<T> createSession(Class<T> componentType);
<T> ConfigurationSession<T> restoreSession(
Configuration<T> configuration);
}
Interface ConfigurationSession
package configurator;
import java.io.Serializable;
import configurator.model.Configuration;
import configurator.task.Agenda;
/**
* (c) 2012 Copyright by Vivian Steller
*/
/**
* Manages the runtime state of a configuration.
*
* @author Vivian Steller
* @since 1.0
*/
public interface ConfigurationSession<T> extends Serializable
{
Class<T> getConfiguredType();
Configuration<T> getConfiguration();
Agenda<T> getAgenda();
void store(String id);
void load(String id);
void restore(Configuration<T> configuration);
void restore(T instance);
void submit();
void close();
'@$
}
Interface Configuration
package configurator.model;
/**
* TODO rename to Model<T>
*/
public interface Configuration<T>
{
/*
* Allows traversal of the configuration.
*/
Component<T> getRootComponent();
/*
* Validates the configuration.
*/
boolean isValid();
/*
* Whether all components, attributes and parts contained within the
* configuration have been specified.
*/
boolean isComplete();
/*
* Allows accessing the underlying configured object.
*/
T getValue();
}
Interface Element
package configurator.model;
public interface Element<T>
{
Component<?> getParent();
T getValue();
void setValue(T value);
}
Interface Component
package configurator.model;
import java.util.Collection;
import configurator.event.Events;
import configurator.event.Listener;
import configurator.metadata.ComponentDescriptor;
/**
* Represents a component of type <code>C</code>. This interface allows
* you to generically manage instances of JavaBean style classes.
* Implementations automatically take care of instantiation, state as
* well as dynamic type changes.<br/>
* <br/>
* While <code>C</code> is considered the base type for this component's
* value, the actual value can have any subtype of <code>C</code>. See
&6R9%R89 &+=+
'@;
* {@link #getType()} for more information.<br/>
* <br/>
* Additionally, the interface supports registering of observers for
* various events that indicate changes to the component's state.<br/>
* <br/>
* Implementations of this class do <i>not</i> have to be implemented
* thread-safe but serializable.<br/>
* <br/>
* <i>Modeling note: methods are designed to be idempotent</i>
*
* @param <C>
* type represented by this component
*/
public interface Component<C> extends VariableTyped<C>, Facetted,
Element<C>
{
/**
* Descriptor containing metadata about the current component's type
* (returned by {@link #getType()}). As the component's type can
* dynamically change at runtime, also the descriptor returned by
* this method varies. However, the descriptor always reflects the
* currently set type of this component which may be any subtype of
* <code>C</code>.<br/>
* <br/>
* The returned {@link ComponentDescriptor} is <i>immutable</i>.
*
* @param <T>
* type corresponding to the value's current type
* (returned by {@link #getType()})
* @return the {@link ComponentDescriptor} associated to the current
* type
*/
<T extends C> ComponentDescriptor<T> getMetadata();
/**
* Gets the base type of the value managed by this component.
*
* @return the component value's base type
*/
Class<C> getBaseType();
/**
* Gets the current type of the value managed by this component.
*
* @param <T>
* the value's current type
* @return the component value's current type
* @see #setType(Class)
*/
<T extends C> Class<T> getType();
/**
* Sets the type of the value managed by this component. The passed
* type must be a subclass of this component's base type
* <code>C</code> and may be declared abstract.<br/>
* <br/>
* The component supports switching between any type for that the
* rules above apply. Especially these type changes are supported:
* <ul>
* <li><i>down the type hierarchy</i>: setting the type to a subtype
* of the component's current type (returned by {@link #getType()})</li>
* <li><i>up the type hierarchy</i>: setting the type to a supertype
* of the component's current type (returned by {@link #getType()})
'@<
* as long as the supertype is a subtype of the base type
* <code>C</code></li>
* <li><i>horizontally in the type hierarchy</i>: setting the type
* to another subtype of the component's base type which is not
* necessarily a subtype or supertype of the component value's
* current type (returned by {@link #getType()})</li>
* </ul>
* The component dynamically adds or removes attributes and parts
* from the component depending on the type change. Further, upon a
* type change the {@link #getMetadata()} method returns the
* descriptor of the newly set type so that the new type is
* reflected.<br/>
* <br/>
* Calling this method triggers the following events:
* {@link TypeChanged}, {@link Changed}
*
* @param <T>
* the value's type to set
* @param type
* the type of the component's value to set
*/
<T extends C> void setType(Class<T> type);
/**
* Whether the current component's type is instantiatable or
* abstract.
*
* @return <code>true</code> if the current type is abstract
* (non-instantiatable)
*/
boolean isAbstract();
/**
* Whether the component is instantiated or not. Instantiated means
* that the component manages an underlying bean instance of type
* <code>C</code> (or a subtype thereof).
*
* @return <code>true</code> if the component is instantiated
* @see #getValue()
* @see #setValue(Object)
*/
boolean isInstantiated();
/**
* Whether the user did specify any property value of this component
* or any of it's sub-components (parts). This method basically
* returns <code>true</code> if any <code>set*</code>-method, such
* as {@link #setAttributeValue(String, Object)},
* {@link #setPartValue(String, Object)}, {@link #setValue(Object)}
* or {@link #setType(Class)} has been invoked.
*
* @return <code>true</code> if the user specified any of this
* component's properties
*/
boolean isSpecified();
/**
* Accesses the instance managed by this component. The bean might
* have been automatically instantiated during the configuration
* process or alternatively must have been explicitly set by the
* user using the {@link #setValue(Object)} method.
*
* @return the underlying bean instance or <code>null</code> if the
&6R9%R89 &+=+
'@?
* component has not been instantiated yet
* @see #setValue(Object)
*/
C getValue();
/**
* Explicitly sets the underlying bean instance. The component's
* attributes and parts are populated with the given value in order
* to reflect the bean instance's state.<br/>
* <br/>
* Calling this method triggers the following events if changes to
* the component's current state are detected: {@link ValueChanged},
* {@link TypeChanged}, {@link Changed}
*
* @param value
* the value to populate this component with
*/
void setValue(C value);
/**
* If this component is a part of another component this method
* returns the containing component otherwise <code>null</code>.
*
* @return the component containing this component if present,
* otherwise <code>null</code>
*/
Component<?> getParent();
/**
* Resets the component's state. The component's type is reset to
* the base type <code>C</code>. The managed instance is set to
* <code>null</code>.<br/>
* <br/>
* Calling this method triggers the following events: {@link Reset},
* {@link Changed}
*/
void reset();
// F A C E T S
/**
* Checks whether the given facet type is defined for the component.
*
* @param facetType
* the facet type to check availability for
* @return <code>true</code> if the component can be viewed as the
* given facet type
*/
boolean hasFacet(Class<?> facetType);
/**
* Obtains the facet view of the given type for this component. The
* returned facet <b>must be</b> cached by the implementation so
* that multiple invocations to this method always return the same
* instance.
*
* @param facetType
* the type of the facet
* @return the component as facet of the given type
*/
<F> F getFacet(Class<F> facetType);
// A T T R I B U T E S
'@@
/**
* Gets the (singular and plural) attributes of this component. The
* attributes returned correspond to the ones that are defined by
* the component's current type (returned by {@link #getType()}).<br/>
* <br/>
* The returned collection is <i>unmodifiable</i>.
*
* @return the attributes of the component
*/
Collection<Attribute<C, ?>> getAttributes();
/**
* Gets a specific (singular or plural) attribute of this component.
* If the component's current type (returned by {@link #getType()})
* doesn't contain the specified attribute an exception is thrown.
*
* @param <A>
* the type of the attribute's value
* @param attributeName
* the name of the attribute to retrieve (may denote a
* singular or plural attribute)
* @return the attribute with the given name
* @throws ModelException
* if the component's type doesn't contain an attribute
* with the given name
*/
<A> Attribute<C, A> getAttribute(String attributeName)
throws ModelException;
/**
* Gets the value of a specific singular attribute of this
* component. If the component's current type (returned by
* {@link #getType()}) doesn't contain the specified attribute or
* the given attribute name doesn't denote a singular attribute an
* exception is thrown.<br/>
* <br/>
* This method is a shortcut for: <code>
* this.getAttribute(attributeName).getValue()
* </code>
*
* @param <A>
* the type of the attribute's value
* @param attributeName
* the name of the attribute whose value to retrieve
* (must denote a singular attribute)
* @return the named attribute's value
* @throws ModelException
* if the component's type doesn't contain a singular
* attribute with the given name
* @see SingularAttribute#getValue()
*/
<A> A getAttributeValue(String attributeName) throws ModelException;
/**
* Sets the value of a specific singular attribute of this
* component. If the component's current type (returned by
* {@link #getType()}) doesn't contain the specified attribute or
* the given attribute name doesn't denote a singular attribute an
* exception is thrown.<br/>
* <br/>
* This method is a shortcut for: <code>
* this.getAttribute(attributeName).setValue(value)
&6R9%R89 &+=+
'@F
* </code>
*
* @param <A>
* the type of the attribute's value
* @param attributeName
* the name of the attribute whose value to retrieve
* (must denote a singular attribute)
* @throws ModelException
* if the component's type doesn't contain a singular
* attribute with the given name
* @see SingularAttribute#setValue(Object)
*/
<A> void setAttributeValue(String attributeName, A value)
throws ModelException;
/**
* Gets the values of a specific plural attribute of this component.
* If the component's current type (returned by {@link #getType()})
* doesn't contain the specified attribute or the given attribute
* name doesn't denote a plural attribute an exception is thrown.<br/>
* <br/>
* This method is a shortcut for: <code>
* this.getAttribute(attributeName).getValue()
* </code>
*
* @param <A>
* the type of the attribute's value
* @param attributeName
* the name of the attribute whose value to retrieve
* (must denote a plural attribute)
* @return the named attribute's values
* @throws ModelException
* if the component's type doesn't contain a plural
* attribute with the given name
* @see PluralAttribute#getValue()
*/
<A> Collection<A> getAttributeValues(String pluralAttributeName)
throws ModelException;
/**
* Sets the values of a specific plural attribute of this component.
* If the component's current type (returned by {@link #getType()})
* doesn't contain the specified attribute or the given attribute
* name doesn't denote a plural attribute an exception is thrown.<br/>
* <br/>
* This method is a shortcut for: <code>
* this.getAttribute(attributeName).setValue(value)
* </code>
*
* @param <A>
* the type of the attribute's value
* @param attributeName
* the name of the attribute whose value to retrieve
* (must denote a plural attribute)
* @throws ModelException
* if the component's type doesn't contain a plural
* attribute with the given name
* @see PluralAttribute#setValue(Object)
*/
<A> void setAttributeValues(String pluralAttributeName,
Collection<A> values) throws ModelException;
/**
'@G
* Resets a specific (singular or plural) attribute of this
* component. If the component's current type (returned by
* {@link #getType()}) doesn't contain the specified attribute an
* exception is thrown.<br/>
* <br/>
* This method is a shortcut for: <code>
* this.getAttribute(attributeName).reset()
* </code>
*
* @param attributeName
* the name of the attribute to reset (may denote a
* singular or plural attribute)
* @throws ModelException
* if the component's type doesn't contain an attribute
* with the given name
* @see Attribute#reset()
*/
void resetAttribute(String attributeName) throws ModelException;
// P A R T S
/**
* Gets the (singular and plural) parts of this component. The parts
* returned correspond to the ones that are defined by the
* component's current type (returned by {@link #getType()}).<br/>
* <br/>
* The returned collection is <i>unmodifiable</i>.
*
* @return the parts of the component
*/
Collection<Part<C, ?>> getParts();
/**
* Gets a specific (singular or plural) part of this component. If
* the component's current type (returned by {@link #getType()})
* doesn't contain the specified part an exception is thrown.
*
* @param <P>
* the type of the part's value
* @param partName
* the name of the part to retrieve (may denote a
* singular or plural part)
* @return the part with the given name
* @throws ModelException
* if the component's type doesn't contain an part with
* the given name
*/
<P> Part<C, P> getPart(String partName) throws ModelException;
/**
* Gets the referenced component of a specific singular part of this
* component. If the component's current type (returned by
* {@link #getType()}) doesn't contain the specified part or the
* given part name doesn't denote a singular part an exception is
* thrown.<br/>
* <br/>
* This method is a shortcut for: <code>
* ((SingularPart) this.getPart(partName)).getPartComponent()
* </code>
*
* @param <P>
* the type of the part's value
* @param partName
&6R9%R89 &+=+
'F(
* the name of the part whose component to retrieve (must
* denote a singular part)
* @return the named part's referenced component
* @throws ModelException
* if the component's type doesn't contain a singular
* part with the given name
* @see SingularPart#getPartComponent()
*/
<P> Component<P> getPartComponent(String partName)
throws ModelException;
/**
* Gets the value of a specific singular part of this component. If
* the component's current type (returned by {@link #getType()})
* doesn't contain the specified part or the given part name doesn't
* denote a singular part an exception is thrown.<br/>
* <br/>
* This method is a shortcut for: <code>
* this.getPart(partName).getValue()
* </code>
*
* @param <P>
* the type of the part's value
* @param partName
* the name of the part whose value to retrieve (must
* denote a singular part)
* @return the named part's value
* @throws ModelException
* if the component's type doesn't contain a singular
* part with the given name
* @see SingularPart#getValue()
*/
<P> P getPartValue(String partName) throws ModelException;
/**
* Sets the value of a specific singular part of this component. If
* the component's current type (returned by {@link #getType()})
* doesn't contain the specified part or the given part name doesn't
* denote a singular part an exception is thrown.<br/>
* <br/>
* This method is a shortcut for: <code>
* this.getPart(partName).setValue(value)
* </code>
*
* @param <P>
* the type of the part's value
* @param partName
* the name of the part whose value to retrieve (must
* denote a singular part)
* @throws ModelException
* if the component's type doesn't contain a singular
* part with the given name
* @see SingularPart#setValue(Object)
*/
<P> void setPartValue(String partName, P value)
throws ModelException;
/**
* Gets the referenced components of a specific plural part of this
* component. If the component's current type (returned by
* {@link #getType()}) doesn't contain the specified part or the
* given part name doesn't denote a plural part an exception is
* thrown.<br/>
'F#
* <br/>
* This method is a shortcut for: <code>
* ((PluralPart) this.getPart(partName)).getPartComponents()
* </code>
*
* @param <E>
* the type of the part's collection elements
* @param partName
* the name of the part whose component to retrieve (must
* denote a plural part)
* @return the named part's referenced components
* @throws ModelException
* if the component's type doesn't contain a plural part
* with the given name
* @see PluralPart#getPartComponents()
*/
<E> Collection<Component<E>>
getPartComponents(String pluralPartName)
throws ModelException;
/**
* Gets the values of a specific plural part of this component. If
* the component's current type (returned by {@link #getType()})
* doesn't contain the specified part or the given part name doesn't
* denote a plural part an exception is thrown.<br/>
* <br/>
* This method is a shortcut for: <code>
* this.getPart(partName).getValue()
* </code>
*
* @param <E>
* the type of the part's collection elements
* @param partName
* the name of the part whose value to retrieve (must
* denote a plural part)
* @return the named part's values
* @throws ModelException
* if the component's type doesn't contain a plural part
* with the given name
* @see PluralPart#getValue()
*/
<E> Collection<E> getPartValues(String pluralPartName)
throws ModelException; // shortcut
// for
// getPart(partName).getValue()
/**
* Sets the values of a specific plural part of this component. If
* the component's current type (returned by {@link #getType()})
* doesn't contain the specified part or the given part name doesn't
* denote a plural part an exception is thrown.<br/>
* <br/>
* This method is a shortcut for: <code>
* this.getPart(partName).setValue(value)
* </code>
*
* @param <E>
* the type of the part's collection elements
* @param partName
* the name of the part whose value to retrieve (must
* denote a plural part)
* @throws ModelException
* if the component's type doesn't contain a plural part
&6R9%R89 &+=+
'F'
* with the given name
* @see PluralPart#setValue(Object)
*/
<E> void setPartValues(String pluralPartName, Collection<E> values)
throws ModelException;
/**
* Resets a specific (singular or plural) part of this component. If
* the component's current type (returned by {@link #getType()})
* doesn't contain the specified part an exception is thrown.<br/>
* <br/>
* This method is a shortcut for: <code>
* this.getPart(partName).reset()
* </code>
*
* @param partName
* the name of the part to reset (may denote a singular
* or plural part)
* @throws ModelException
* if the component's type doesn't contain an part with
* the given name
* @see Part#reset()
*/
void resetPart(String partName) throws ModelException;
/**
* Accepts a component hierarchy visitor and invokes its methods for
* any attribute and part found in this component (in
* <em>breadth-first</em> order). Recursively calls
* {@link #accept(Visitor)} on any of the part's components.
*
* @param visitor
* the visitor to invoke
*/
void accept(Visitor visitor);
// L I S T E N E R S
/**
* Registers a listener for the {@link Changed} event.
*
* @param listener
* the listener to register
* @see Changed
*/
void addChangeListener(ChangeListener<C> listener);
/**
* Unregisters a listener for the {@link Changed} event.
*
* @param listener
* the listener to unregister
* @see Changed
*/
void removeChangeListener(ChangeListener<C> listener);
/**
* Registers a listener for the {@link ValueInstantiated} event.
*
* @param listener
* the listener to register
* @see ValueInstantiated
*/
'F$
void addValueInstantiationListener(
ValueInstantiationListener<C> listener);
/**
* Unregisters a listener for the {@link ValueInstantiated} event.
*
* @param listener
* the listener to unregister
* @see ValueInstantiated
*/
void removeValueInstantiationListener(
ValueInstantiationListener<C> listener);
/**
* Registers a listener for the {@link ValueChanged} event.
*
* @param listener
* the listener to register
* @see ValueChanged
*/
void
addValueChangeListener(
ValueChangeListener<C> valueChangedListener);
/**
* Unregisters a listener for the {@link ValueChanged} event.
*
* @param listener
* the listener to unregister
* @see ValueChanged
*/
void removeValueChangeListener(
ValueChangeListener<C> valueChangedListener);
/**
* Registers a listener for the {@link TypeChanged} event.
*
* @param listener
* the listener to register
* @see TypeChanged
*/
void
addTypeChangeListener(TypeChangeListener<C> typeChangeListener);
/**
* Unregisters a listener for the {@link TypeChanged} event.
*
* @param listener
* the listener to unregister
* @see TypeChanged
*/
void
removeTypeChangeListener(
TypeChangeListener<C> typeChangeListener);
/**
* Registers a listener for the {@link Reset} event.
*
* @param listener
* the listener to register
* @see Reset
*/
void addResetListener(ResetListener<C> listener);
&6R9%R89 &+=+
'F;
/**
* Unregisters a listener for the {@link Reset} event.
*
* @param listener
* the listener to unregister
* @see Reset
*/
void removeResetListener(ResetListener<C> listener);
/**
* Event listener for the {@link Changed} event.
*
* @param <C>
* type of the changed component's value
* @see Changed
* @author Vivian Steller
* @since 1.0
*/
interface ChangeListener<C> extends Listener
{
void handle(Changed<C> event);
}
/**
* Event listener for the {@link ValueInstantiated} event.
*
* @param <C>
* type of the instantiated value
* @see ValueInstantiated
* @author Vivian Steller
* @since 1.0
*/
interface ValueInstantiationListener<C> extends Listener
{
void handle(ValueInstantiated<C> event);
}
/**
* Event listener for the {@link ValueChanged} event.
*
* @param <C>
* type of the changed value
* @see ValueChanged
* @author Vivian Steller
* @since 1.0
*/
interface ValueChangeListener<C> extends Listener
{
void handle(ValueChanged<C> event);
}
/**
* Event listener for the {@link TypeChanged} event.
*
* @param <C>
* base type of the component's value whose type has
* changed
* @see TypeChanged
* @author Vivian Steller
* @since 1.0
*/
interface TypeChangeListener<C> extends Listener
'F<
{
void handle(TypeChanged<C> event);
}
/**
* Event listener for the {@link Reset} event.
*
* @param <C>
* type of the reset component's value
* @see ValueInstantiated
* @author Vivian Steller
* @since 1.0
*/
interface ResetListener<C> extends Listener
{
void handle(Reset<C> event);
}
// E V E N T S
// Change
/**
* Event indicating that the component's state changed.<br/>
* <br/>
* This event is fired upon any component state changes, e.g. value
* changed, type changed etc. Usually other events such as
* {@link ValueChanged} or {@link TypeChanged} have been fired
* before.<br/>
* <br/>
* Change detection is implemented transitively, that is, if one of
* the component's attributes or parts changes, the change is
* propagated to the component and the respective event is fired.
*
* @param <C>
* base type managed by the component
* @author Vivian Steller
* @since 1.0
*/
static class Changed<C> extends
Events.Changed<Component<C>, ChangeListener<C>>
{
public Changed(Component<C> source)
{
super(source);
}
protected void call(ChangeListener<C> listener)
{
listener.handle(this);
}
}
// Value Instantiation
/**
* Event indicating that the component's value has been
* instantiated.<br/>
*
* @param <C>
* base type managed by the component
* @author Vivian Steller
* @since 1.0
*/
&6R9%R89 &+=+
'F?
static class ValueInstantiated<C>
extends
Events.ValueInstantiated<Component<C>, C,
ValueInstantiationListener<C>>
{
public ValueInstantiated(Component<C> source, C newValue)
{
super(source, newValue);
}
protected void call(ValueInstantiationListener<C> listener)
{
listener.handle(this);
}
}
// Value Change
/**
* Event indicating that the component's value changed.<br/>
* <br/>
* Change detection is implemented transitively, that is, if one of
* the component's attributes or parts changes, the change is
* propagated to the component and the respective event is fired.
*
* @param <C>
* base type managed by the component
* @see Component#getValue()
* @author Vivian Steller
* @since 1.0
*/
static class ValueChanged<C> extends
Events.ValueChanged<Component<C>, C, ValueChangeListener<C>>
{
public ValueChanged(Component<C> source, C oldValue, C newValue)
{
super(source, oldValue, newValue);
}
protected void call(ValueChangeListener<C> listener)
{
listener.handle(this);
}
protected static <C> ValueChanged<C> create(
Component<C> source,
C oldValue, C newValue)
{
return new ValueChanged<C>(source, oldValue, newValue)
{
};
}
}
// Type Change
/**
* Event indicating that the component's type changed.<br/>
*
* @param <C>
* bae type managed by the component
* @see Component#getType()
* @author Vivian Steller
* @since 1.0
*/
'F@
static class TypeChanged<C> extends
Events.TypeChanged<Component<C>, C, TypeChangeListener<C>>
{
public TypeChanged(Component<C> source,
Class<? extends C> oldType, Class<? extends C> newType)
{
super(source, oldType, newType);
}
protected void call(TypeChangeListener<C> listener)
{
listener.handle(this);
}
}
// Reset
/**
* Event indicating that the component has been reset.<br/>
*
* @param <C>
* base type managed by the component
* @see Component#reset()
* @author Vivian Steller
* @since 1.0
*/
static class Reset<C> extends
Events.Reset<Component<C>, ResetListener<C>>
{
public Reset(Component<C> source)
{
super(source);
}
protected void call(ResetListener<C> listener)
{
listener.handle(this);
}
}
// V I S I T O R
/**
* Visitor interface that is used to implement the visitor design
* pattern on component hierarchies.
*
* @author Vivian Steller
* @since 1.0
*/
static interface Visitor
{
/**
* Invoked by {@link Component#accept(Visitor)} for each
* component in the hierarchy.
*
* @param component
* the component to be visited
*/
void visit(Component<?> component);
/**
* Invoked by {@link Component#accept(Visitor)} for each
* attribute in the hierarchy.
*
&6R9%R89 &+=+
'FF
* @param attribute
* the attribute to be visited
*/
void visit(Attribute<?, ?> attribute);
/**
* Invoked by {@link Component#accept(Visitor)} for each part in
* the hierarchy.
*
* @param part
* the part to be visited
*/
void visit(Part<?, ?> part);
}
}
Interface Attribute
package configurator.model;
import configurator.event.Events;
import configurator.event.Listener;
import configurator.metadata.AttributeDescriptor;
/**
* Represents an attribute of type <code>A</code>. This interface allows
* you to generically manage <i>simple typed</i> properties of
* JavaBean-style instances.<br/>
* <br/>
* Opposed to {@link Part}s, attributes are "atomic" and not further
* divisible, which means that their value has to be set "at once".
* Further more, again in contrast to {@link Part}s whose value's type
* may vary at runtime, the type of the attribute's value is fixed.<br/>
* <br/>
* There exist two subtypes of this interface {@link SingularAttribute}
* and {@link PluralAttribute} to distinguish between non-collection
* valued and collection valued attributes.<br/>
* <br/>
* Additionally, this interface supports registering of observers for
* various events that indicate changes to the attribute's state.<br/>
* <br/>
* Implementations of this class do <i>not</i> have to be implemented
* thread-safe but serializable.<br/>
* <br/>
* <i>Modeling note: methods are designed to be idempotent</i>
*
* @param <C>
* base type of the component containing the attribute
* @param <A>
* type of the value managed by this attribute
* @see SingularAttribute
* @see PluralAttribute
*/
public abstract interface Attribute<C, A> extends Element<A>
{
/**
* Descriptor containing metadata about the attribute.<br/>
* <br/>
* The returned {@link AttributeDescriptor} is <i>immutable</i>.
*
* @param <T>
* type that declares the attribute
* @param <A>
'FG
* type of this attribute's value
* @return the {@link AttributeDescriptor} associated to the
* attribute
*/
<T extends C> AttributeDescriptor<T, A> getMetadata();
/**
* Name of the attribute.
*
* @return the name of the attribute
*/
String getName();
/**
* Component that this attribute is attached to.
*
* @return the component containing this attribute
*/
Component<C> getParent();
/**
* Whether the attribute value is instantiated (non-
* <code>null</code>) or not.
*
* @return <code>true</code> if the attribute is instantiated
* @see #getValue()
* @see #setValue(Object)
*/
boolean isInstantiated();
/**
* Whether the user did specify the value of this attribute.
*
* @return <code>true</code> if the user specified the value of this
* attribute
*/
boolean isSpecified();
/**
* Accesses the value managed by this attribute. The value must have
* been explicitly set by the user using the
* {@link #setValue(Object)} method or the containing component's
* type is instantiated and provides a default value for the
* attribute.
*
* @return the current attribute's value or <code>null</code> if the
* attribute's value has not been set yet
* @see #setValue(Object)
*/
A getValue();
/**
* Sets the value of the attribute. <br/>
* Calling this method triggers the following events if changes to
* the attribute's state are detected: {@link Changed}
*
* @param value
* the attribute value to set
*/
void setValue(A value);
/**
* Resets the attribute's state. The attribute value is set to
&6R9%R89 &+=+
'G(
* <code>null</code> or the default value (refer to
* {@link #getValue()}).<br/>
* <br/>
* Calling this method triggers the following events:
* {@link Changed}
*/
void reset();
// L I S T E N E R S
/**
* Registers a listener for the {@link Changed} event.
*
* @param listener
* the listener to register
* @see Changed
*/
void addChangeListener(ChangeListener<C, A> listener);
/**
* Unregisters a listener for the {@link Changed} event.
*
* @param listener
* the listener to unregister
* @see Changed
*/
void removeChangeListener(ChangeListener<C, A> listener);
/**
* Event listener for the {@link Changed} event.
*
* @param <C>
* base type of the component containing the attribute
* @param <A>
* type of the changed attribute's value
* @see Changed
* @author Vivian Steller
* @since 1.0
*/
interface ChangeListener<C, A> extends Listener
{
void handle(Changed<C, A> event);
}
// E V E N T S
// Change
/**
* Event indicating that the attribute's state changed.
*
* @param <C>
* base type of the component containing the attribute
* @param <A>
* type of the changed attribute's value
* @author Vivian Steller
* @since 1.0
*/
class Changed<C, A> extends
Events.Changed<Attribute<C, A>, ChangeListener<C, A>>
{
public Changed(Attribute<C, A> source)
{
super(source);
'G#
}
protected void call(ChangeListener<C, A> listener)
{
listener.handle(this);
}
}
}
Interface Part
package configurator.model;
import configurator.event.Events;
import configurator.event.Listener;
import configurator.metadata.PartDescriptor;
/**
* Represents a part relationship between a component of type
* <code>C</code> and one or more other components of type
* <code>P</code>. This interface allows you to generically manage
* <i>complex typed</i> properties of JavaBean-style instances.<br/>
* <br/>
* Opposed to {@link Attribute}s, parts are "complex" and may itself
* contain other attributes or parts (or more precisely the referenced
* part component can do so). The value of a part may explicitly set or
* may be automatically instantiated by the framework while the user
* specifies the concrete type, specific attribute or sub-part values.
* Further more, in contrast to {@link Attribute}s whose value's type is
* fixed, the part's type may vary at runtime according to the rules
* defined by {@link Component#setType(Class)}.<br/>
* <br/>
* There exist two subtypes of this interface {@link SingularPart} and
* {@link PluralPart} to distinguish between non-collection valued and
* collection valued parts.<br/>
* <br/>
* Additionally, this interface supports registering of observers for
* various events that indicate changes to the part's state.<br/>
* <br/>
* Implementations of this class do <i>not</i> have to be implemented
* thread-safe but serializable.<br/>
* <br/>
* <i>Modeling note: methods are designed to be idempotent</i>
*
* @param <C>
* base type of the component containing the part
* @param <P>
* base type of the value managed by this part
* @see SingularPart
* @see PluralPart
* @author Vivian Steller
* @since 1.0
*/
public abstract interface Part<C, P> extends Element<P>
{
/**
* Descriptor containing metadata about the part. Although the part
* component's type can vary at runtime, the descriptor returned by
* this method remains constant as it represents information about
* the part itself and not information about the component
* referenced by this part.<br/>
* <br/>
* The returned {@link PartDescriptor} is <i>immutable</i>.
&6R9%R89 &+=+
'G'
*
* @param <T>
* type that declares the part
* @param <P>
* base type of this part's value
* @return the {@link PartDescriptor} associated to the attribute
*/
<T extends C> PartDescriptor<T, P> getMetadata();
/**
* Name of the part.
*
* @return the name of the part
*/
String getName();
/**
* Component that this part is attached to.
*
* @return the component containing this part
*/
Component<C> getParent();
/**
* Whether the part value is instantiated (non-<code>null</code>) or
* not.<br/>
* <br/>
* This method delegates to the referenced part component(s).
*
* @return <code>true</code> if the part is instantiated
* @see #getValue()
* @see #setValue(Object)
*/
boolean isInstantiated();
/**
* Whether the user did specify the value of this part or any of the
* part component's attributes or parts.<br/>
* <br/>
* This method delegates to the referenced part component(s).
*
* @return <code>true</code> if the user specified any of this
* part's properties
*/
boolean isSpecified();
/**
* Accesses the instance(s) managed by this part. The bean might
* have been automatically instantiated during the configuration
* process or must have been explicitly set by the user using the
* {@link #setValue(Object)} method. Alternatively, the method
* returns a default value if the containing component's type is
* instantiated and provides a default value for the part<br/>
* <br/>
* This method delegates to the referenced part component(s).
*
* @return the underlying bean instance or <code>null</code> if the
* part has not been instantiated yet
* @see #setValue(Object)
*/
P getValue();
/**
'G$
* Explicitly sets the underlying bean instance. The part
* component(s)' attributes and parts are populated with the given
* value in order to reflect the bean instance's state.<br/>
* <br/>
* Calling this method triggers the following events if changes to
* the part's current state are detected: {@link ValueChanged},
* {@link Changed} and the events triggered by calling this part
* component(s)' {@link Component#setValue(Object)} method.<br/>
* <br/>
* This method delegates to the referenced part component(s).
*
* @param value
* the value to populate this part with
*/
void setValue(P value);
/**
* Resets the part's state. The part component(s)' type is reset to
* their base type <code>P</code>. The managed instance is set to
* <code>null</code> or the default value (refer to
* {@link #getValue()}).<br/>
* <br/>
* Calling this method triggers the following events:
* {@link Changed} and the events triggered by calling this part
* component(s)' {@link Component#reset()} method. <br/>
* This method delegates to the referenced part component(s).
*/
void reset();
// E V E N T S
/**
* Registers a listener for the {@link Changed} event.
*
* @param listener
* the listener to register
* @see Changed
*/
void addChangeListener(ChangeListener<C, P> listener);
/**
* Unregisters a listener for the {@link Changed} event.
*
* @param listener
* the listener to unregister
* @see Changed
*/
void removeChangeListener(ChangeListener<C, P> listener);
/**
* Registers a listener for the {@link ValueChanged} event.
*
* @param listener
* the listener to register
* @see ValueChanged
*/
void addValueChangeListener(ValueChangeListener<C, P> listener);
/**
* Unregisters a listener for the {@link ValueChanged} event.
*
* @param listener
* the listener to unregister
&6R9%R89 &+=+
'G;
* @see ValueChanged
*/
void removeValueChangeListener(ValueChangeListener<C, P> listener);
/**
* Event listener for the {@link Changed} event.
*
* @param <C>
* base type of the component containing the part
* @param <P>
* base type of the changed part's referenced component
* @see Changed
* @author Vivian Steller
* @since 1.0
*/
interface ChangeListener<C, P> extends Listener
{
void handle(Changed<C, P> event);
}
/**
* Event listener for the {@link ValueChanged} event.
*
* @param <C>
* base type of the component containing the part
* @param <P>
* base type of the changed part's referenced component
* @see ValueChanged
* @author Vivian Steller
* @since 1.0
*/
interface ValueChangeListener<C, P> extends Listener
{
void handle(ValueChanged<C, P> event);
}
// Change
/**
* Event indicating that the part's state changed.<br/>
* <br/>
* This event is fired upon any part state changes which corresponds
* to the state changes of this part's referenced component(s).<br/>
* <br/>
* Change detection is implemented transitively, that is, if one of
* the part component(s)' attributes or parts changes, the change is
* propagated to the part and the respective event is fired.
*
* @param <C>
* base type of the component containing the part
* @param <P>
* base type of the changed part's referenced component
* @author Vivian Steller
* @since 1.0
*/
class Changed<C, P> extends
Events.Changed<Part<C, P>, ChangeListener<C, P>>
{
public Changed(Part<C, P> source)
{
super(source);
}
protected void call(ChangeListener<C, P> listener)
'G<
{
listener.handle(this);
}
}
// Value Change
/**
* Event indicating that the part's value changed.<br/>
* <br/>
* Change detection is implemented transitively, that is, if one of
* the part component(s)' attributes or parts changes, the change is
* propagated to the part and the respective event is fired.
*
* @param <C>
* base type managed by the component
* @param <P>
* base type of the changed part's referenced component
* @see Part#getValue()
* @author Vivian Steller
* @since 1.0
*/
class ValueChanged<C, P> extends
Events.ValueChanged<Part<C, P>, P, ValueChangeListener<C, P>>
{
public ValueChanged(Part<C, P> source, P oldValue, P newValue)
{
super(source, oldValue, newValue);
}
protected void call(ValueChangeListener<C, P> listener)
{
listener.handle(this);
}
}
}
Interface ComponentDescriptor
package configurator.metadata;
import java.util.Map;
import configurator.model.Facetted;
/**
* Holds meta data for a configurable type <code>C</code>.
*/
public interface ComponentDescriptor<C> extends Facetted
{
/**
* The type that this descriptor describes.
*
* @return the Java class that is described by this component
* descriptor
*/
Class<C> getValueType();
/**
* Attributes of <code>C</code>. Maps attribute names to the
* respective descriptors.<br/>
* <br/>
* The returned map is <i>unmodifiable</i>.
*
&6R9%R89 &+=+
'G?
* @return the map of attributes of <code>C</code>
*/
Map<String, AttributeDescriptor<C, ?>> getAttributes();
/**
* Parts of <code>C</code>. Maps part names to the respective
* descriptors.<br/>
* <br/>
* The returned map is <i>unmodifiable</i>.
*
* @return the map of parts of <code>C</code>
*/
Map<String, PartDescriptor<C, ?>> getParts();
boolean hasFacet(Class<?> facetType);
<F> F getFacet(Class<F> facetType);
}
Interface AttributeDescriptor
package configurator.metadata;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Member;
import java.util.Collection;
import configurator.model.Typed;
import configurator.util.ValueDelegate;
/**
* Holds meta data of an attribute of component <code>C</code>. The
* attribute's value is of type <code>A</code>.
*
* @param <C>
* type of the class that declares the attribute
* @param <A>
* type of the attribute's value
*/
public abstract interface AttributeDescriptor<C, A>
{
/**
* Descriptor that contains the attribute.
*
* @return the descriptor that contains the attribute
*/
ComponentDescriptor<C> getComponentDescriptor();
/**
* Type that declares the attribute.
*
* @return the type that declares the attribute
*/
Class<C> getDeclaringType();
/**
* Member that this attribute is built from.
*
* @return the Java bean member that this attribute is built from
*/
Member getDeclaringMember();
'G@
/**
* Annotated element that this attribute is built from.
*
* @return the annotated Java bean element that this attribute is
* built from
*/
AnnotatedElement getDeclaringAnnotatedElement();
/**
* Name of the attribute.
*
* @return the name of the attribute
*/
String getName();
/**
* Type of the attribute which corresponds to type of the field or
* accessor method that this attribute maps to. E.g.
* <code>Collection<A></code> if this is a collection attribute.
*
* @return the type of the attribute
*/
Class<A> getValueType();
/**
* Whether this attribute is a collection.
*
* @return <code>true</code> if this attribute is {@link Collection}
* valued
*/
boolean isCollection();
/**
* Whether this attribute is read-only or can be written.
*
* @return <code>true</code> if this is a read-only attribute
*/
boolean isReadOnly();
/**
* Factory method to create a {@link ValueDelegate} that is capable
* of reading or writing the attribute value on the given type
* <code>C</code>.
*
* @param instance
* the instance from/to which the attribute value is
* read/written
* @return {@link ValueDelegate} that operates on the given instance
* or <code>null</code> if either instance is
* <code>null</code> or instance doesn't contain the
* property, referenced by this attribute.
*/
ValueDelegate<A> createValueDelegate(C instance);
/**
* @param <C>
* type of the class that declares the attribute
* @param <A>
* type of the attribute's value
* @author Vivian Steller
* @since 1.0
*/
interface SingularAttributeDescriptor<C, A> extends
&6R9%R89 &+=+
'GF
AttributeDescriptor<C, A>, Typed<A>
{
}
/**
* @param <C>
* type of the class that declares the attribute
* @param <A>
* type of the attribute's value
* @param <E>
* element type of the collection
* @author Vivian Steller
* @since 1.0
*/
interface PluralAttributeDescriptor<C, A, E> extends
AttributeDescriptor<C, A>, Typed<E>
{
}
/**
* Builder interface for creating (immutable)
* {@link AttributeDescriptor}s.
*
* @author Vivian Steller
* @since 1.0
*/
public static interface Builder<C, A, T>
{
/**
* Specifies the component descriptor that owns the attribute
* being built. The passed component descriptor might not be
* fully initialized yet, that is, not all attributes, parts and
* facets have been instantiated and added to the component
* descriptor.
*
* @param componentDescriptor
* the (not necessarily fully initialized) component
* descriptor that owns the built attribute
* @return the builder for fluent invocations
*/
Builder<C, A, T> owningDescriptor(
ComponentDescriptor<C> componentDescriptor);
/**
* Specifies the property that the built descriptor is bound to.<br/>
* <br/>
* The specification of the property is <em>required</em>.
*
* @param property
* the property to that the built instance should be
* bound
* @return the builder for fluent invocations
*/
Builder<C, A, T> property(Property<A> property);
/**
* Specifies the component type that declares the attribute.<br/>
* <br/>
* The specification of the component type is <em>optional</em>
* and defaults to the property's
* {@link Property#getDeclaringClass()} property.
*
* @param declaringType
'GG
* the component type that declares the attribute
* @return the builder for fluent invocations
*/
Builder<C, A, T> declaringType(Class<C> declaringType);
/**
* Specifies the name of the built attribute.<br/>
* <br/>
* The specification of the name is <em>optional</em> and
* defaults to the property's {@link Property#getName()}
* property.
*
* @param name
* the name of the built attribute
* @return the builder for fluent invocations
*/
Builder<C, A, T> name(String name);
/**
* Specifies the type of the built attribute's bound property.<br/>
* <br/>
* The specification of the member type is <em>optional</em> and
* defaults to the property's {@link Property#getJavaClass()}
* property.
*
* @param memberType
* the member type of the built attribute's bound
* property
* @return the builder for fluent invocations
*/
Builder<C, A, T> memberType(Class<A> memberType);
/**
* Specifies the type of the built attribute.<br/>
* <br/>
* The specification of the type is <em>optional</em> and is by
* default determined from to the property's
* {@link Property#getJavaClass()} property.
*
* @param baseType
* the base type of the built attribute
* @return the builder for fluent invocations
*/
Builder<C, A, T> baseType(Class<T> baseType);
/**
* Retrieves the attribute descriptor instance built by this
* builder. If this method is called by framework, the component
* descriptor passed to the builder via the
* {@link #owningDescriptor(ComponentDescriptor)} method may not
* be fully initialized, that is, not all attributes, parts and
* facets have been instantiated yet.<br/>
* <br/>
* Refer to {@link #initialize()} which is called when the
* component descriptor is fully initialized.
*
* @return the (not necessarily fully initialized) attribute
* descriptor
*/
AttributeDescriptor<C, A> build();
/**
* Finally initializes the attribute descriptor built by this
&6R9%R89 &+=+
$((
* builder. Invoked when the descriptor that this attribute is
* part of, has been fully initialized, that is, all attributes,
* parts and facets (whose initialize method may or may not have
* been called though) are available.
*
* @return the fully initialized attribute descriptor
*/
AttributeDescriptor<C, A> initialize();
}
}
Interface PartDescriptor
package configurator.metadata;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Member;
import java.util.Collection;
import configurator.model.Typed;
import configurator.util.ValueDelegate;
/**
* Holds meta data of a part of component <code>C</code>. The part's
* value is of type <code>P</code>.
*
* @param <C>
* type of the class that declares the part
* @param <P>
* type of the part's value
*/
public abstract interface PartDescriptor<C, P>
{
/**
* Descriptor that contains the part.
*
* @return the descriptor that contains the part
*/
ComponentDescriptor<C> getComponentDescriptor();
/**
* Type that declares the part.
*
* @return the type that declares the part
*/
Class<C> getDeclaringType();
/**
* Member that this part is built from.
*
* @return the Java bean member that this part is built from
*/
Member getDeclaringMember();
/**
* Annotated element that this part is built from.
*
* @return the annotated Java bean element that this part is built
* from
*/
AnnotatedElement getDeclaringAnnotatedElement();
/**
$(#
* Name of the part.
*
* @return the name of the part
*/
String getName();
/**
* Base type of the part which corresponds to type of the field or
* accessor method that this part maps to. E.g.
* <code>Collection<P></code> if this is a collection part.
*
* @return the base type of the part's value
*/
Class<P> getValueType();
/**
* Whether this part is a collection.
*
* @return <code>true</code> if this part is {@link Collection}
* valued
*/
boolean isCollection();
/**
* Factory method to create a {@link ValueDelegate} that is capable
* of reading or writing the part value on the given type
* <code>C</code>.
*
* @param instance
* the instance from/to which the part value is
* read/written
* @return {@link ValueDelegate} that operates on the given instance
* or <code>null</code> if either instance is
* <code>null</code> or instance doesn't contain the
* property, referenced by this part.
*/
ValueDelegate<P> createValueDelegate(C instance);
/**
* @param <C>
* type of the class that declares the part
* @param <A>
* type of the part's value
* @author Vivian Steller
* @since 1.0
*/
interface SingularPartDescriptor<C, P> extends
PartDescriptor<C, P>, Typed<P>
{
}
/**
* @param <C>
* type of the class that declares the part
* @param <A>
* type of the part's value
* @param <E>
* element type of the collection
* @author Vivian Steller
* @since 1.0
*/
interface PluralPartDescriptor<C, P, E> extends
PartDescriptor<C, P>, Typed<E>
&6R9%R89 &+=+
$('
{
}
/**
* Builder interface for creating (immutable) {@link PartDescriptor}
* s
*
* @author Vivian Steller
* @since 1.0
*/
public interface Builder<C, P, E>
{
/**
* Specifies the component descriptor that owns the part being
* built. The passed component descriptor might not be fully
* initialized yet, that is, not all attributes, parts and
* facets have been instantiated and added to the component
* descriptor.
*
* @param componentDescriptor
* the (not necessarily fully initialized) component
* descriptor that owns the built attribute
* @return the builder for fluent invocations
*/
Builder<C, P, E> owningDescriptor(
ComponentDescriptor<C> componentDescriptor);
/**
* Specifies the property that the built descriptor is bound to.
* <br/>
* The specification of the property is <em>required</em>.
*
* @param property
* the property to that the built instance should be
* bound
* @return the builder for fluent invocations
*/
Builder<C, P, E> property(Property<P> property);
/**
* Specifies the component type that declares the part.<br/>
* <br/>
* The specification of the component type is <em>optional</em>
* and defaults to the property's
* {@link Property#getDeclaringClass()} property.
*
* @param declaringType
* the component type that declares the part
* @return the builder for fluent invocations
*/
Builder<C, P, E> declaringType(Class<C> declaringType);
/**
* Specifies the name of the built part.<br/>
* <br/>
* The specification of the name is <em>optional</em> and
* defaults to the property's {@link Property#getName()}
* property.
*
* @param name
* the name of the built part
* @return the builder for fluent invocations
*/
$($
Builder<C, P, E> name(String name);
/**
* Specifies the type of the built part's bound property.<br/>
* <br/>
* The specification of the member type is <em>optional</em> and
* defaults to the property's {@link Property#getJavaClass()}
* property.
*
* @param memberType
* the member type of the built part's bound property
* @return the builder for fluent invocations
*/
Builder<C, P, E> memberType(Class<P> memberType);
/**
* Specifies the type of the built part.<br/>
* <br/>
* The specification of the type is <em>optional</em> and is by
* default determined from to the property's
* {@link Property#getJavaClass()} property.
*
* @param baseType
* the base type of the built part
* @return the builder for fluent invocations
*/
Builder<C, P, E> baseType(Class<E> baseType);
/**
* Retrieves the part descriptor instance built by this builder.
* If this method is called by framework, the component
* descriptor passed to the builder via the
* {@link #owningDescriptor(ComponentDescriptor)} method may not
* be fully initialized, that is, not all attributes, parts and
* facets have been instantiated yet.<br/>
* <br/>
* Refer to {@link #initialize()} which is called when the
* component descriptor is fully initialized.
*
* @return the (not necessarily fully initialized) part
* descriptor
*/
PartDescriptor<C, P> build();
/**
* Finally initializes the attribute descriptor built by this
* builder. Invoked when the descriptor that this part is part
* of, has been fully initialized, that is, all attributes,
* parts and facets (whose initialize method may or may not have
* been called though) are available.
*
* @return the fully initialized attribute descriptor
*/
PartDescriptor<C, P> initialize();
}
}
Interface Product
package configurator.product;
import java.util.Collection;
&6R9%R89 &+=+
$(;
import javax.enterprise.util.TypeLiteral;
import configurator.model.Attribute;
import configurator.model.Part;
public interface Product<T>
{
/**
* Name of the product. Usually the attribute annotated with
* {@link info.openconfigurator.products.annotation.Product.Name}.
*
* @return the name of the product
*/
String getName();
/**
* Description of the product. Usually the attribute annotated with
* {@link info.openconfigurator.products.annotation.Product.Description}
* .
*
* @return the description of the product
*/
String getDescription();
Asset getImage();
/**
* Attributes of the product. Usually attributes annotated with
* {@link info.openconfigurator.products.annotation.Product.Attribute}
* .
*
* @return the attributes of the product
*/
Collection<Attribute<T, ?>> getAttributes();
/**
* Attributes of the product with the given level(s). Usually
* attributes annotated with
* {@link info.openconfigurator.products.annotation.Product.Attribute}
* whereby the annotation's level attribute is specified.<br/>
* <br/>
* The level is interpreted as bit mask.
*
* @param level
* the level(s) to retrieve
* @return the attributes of the product fulfilling the given levels
*/
Collection<Attribute<T, ?>> getAttributes(int level);
/**
* Parts of the product.
*
* @return the parts of the product
*/
Collection<Part<T, ?>> getParts();
public static class Literal
{
public static <T> Class<Product<T>> forType(Class<T> type)
{
return new TypeLiteral<Product<T>>()
{
}.getRawType();
$(<
}
}
}
Interface Configuration (Facet)
package configurator.configuration;
import java.util.Collection;
import configurator.model.Attribute;
import configurator.model.Part;
public interface Configuration<T>
{
SpecificationMethod getSpecificationMethod();
AttributeType getAttributeType(Attribute<T, ?> attribute);
Collection<Attribute<T, ?>> getAttributes(AttributeType type);
PartType getPartType(Part<T, ?> part);
Collection<Part<T, ?>> getParts(PartType type);
SpecificationMethod
getSpecificationMethod(Part<T, ?> configuredPart);
}
Interface Data
package configurator.data;
import configurator.model.Attribute;
import configurator.model.Part;
public interface Data<T>
{
// D O M A I N S
DomainScope getDomainScope();
/**
* The initial component type domain. Domains contain values that
* were subject to initial constraint application. Though, no user
* specification has happened so far, which could have lead to
* domain changes.
*/
Domain<Class<? extends T>> getInitialComponentTypeDomain();
Domain<Class<? extends T>> getComponentTypeDomain();
/**
* The initial component value domain. Domains contain values that
* were subject to initial constraint application. Though, no user
* specification has happened so far, which could have lead to
* domain changes.
*/
Domain<T> getInitialComponentValueDomain();
Domain<T> getComponentValueDomain();
/**
* The initial attribute value domain. Domains contain values that
&6R9%R89 &+=+
$(?
* were subject to initial constraint application. Though, no user
* specification has happened so far, which could have lead to
* domain changes.
*/
<A> Domain<A> getInitialAttributeValueDomain(
Attribute<T, A> attribute);
<A> Domain<A> getAttributeValueDomain(Attribute<T, A> attribute);
// not yet implemented
Domain<Integer> getInitialAttributeQuantityDomain(
Attribute<T, ?> attribute);
// not yet implemented
Domain<Integer>
getAttributeQuantityDomain(Attribute<T, ?> attribute);
/**
* The initial part type domain. Domains contain values that were
* subject to initial constraint application. Though, no user
* specification has happened so far, which could have lead to
* domain changes.
*/
<P> Domain<Class<? extends P>> getInitialPartTypeDomain(
Part<T, P> part);
<P> Domain<Class<? extends P>> getPartTypeDomain(Part<T, P> part);
/**
* The initial part value domain. Domains contain values that were
* subject to initial constraint application. Though, no user
* specification has happened so far, which could have lead to
* domain changes.
*/
<P> Domain<P> getInitialPartValueDomain(Part<T, P> part);
/**
* May return <code>null</code>/unbound domain, if domain is not
* explicitly defined using @Domain.Query on neither the part nor
* the referenced component type. In this case, attribute level
* domain definitions are assumed.
*/
<P> Domain<P> getPartValueDomain(Part<T, P> part);
// not yet implemented
Domain<Integer> getInitialPartQuantityDomain(Part<T, ?> part);
// not yet implemented
Domain<Integer> getPartQuantityDomain(Part<T, ?> part);
// D E F A U L T S
Class<? extends T> getDefaultComponentType();
T getDefaultComponentValue();
<A> A getDefaultAttributeValue(Attribute<T, A> attribute);
// not yet implemented
Integer getDefaultAttributeQuantity(Attribute<T, ?> attribute);
<P> Class<? extends P> getDefaultPartType(Part<T, P> part);
$(@
<P> P getDefaultPartValue(Part<T, P> part);
// not yet implemented
Integer getDefaultPartQuantity(Part<T, ?> part);
}
Interface Domain
package configurator.data;
/**
* Represents a domain of something.
*/
public interface Domain<T> extends Cloneable
{
Class<T> getValueType();
DomainType getDomainType();
boolean isOrdered();
boolean isNumeric();
/**
* Determines the number of values contained in the domain.
*
* @return the number of values.
*/
int getSize();
boolean isEmpty();
boolean isFixed();
T getValue();
boolean isEnumerable();
/**
* Whether the domain's values are enumerable or not.
*
* @param threshold
* the maximum number of items, the domain is considered
* enumerable.
* @return <code>true</code> if the domain's value are enumerable
* and the number of items is less than or equal to
* <code>threshold</code>.
*/
boolean isEnumerable(int threshold);
Iterable<T> getValues();
boolean contains(T value);
/**
* Whether the domain's size is unlimited or not.
*
* @return <code>true</code> if the domain is limited,
* <code>false</code> otherwise.
*/
boolean isBounded();
boolean isBoundedAbove();
&6R9%R89 &+=+
$(F
boolean isBoundedBelow();
T getUpperBound();
T getLowerBound();
}
Interface Validation
package configurator.validation;
import java.util.Collection;
import configurator.model.Attribute;
import configurator.model.Part;
public interface Validation<T>
{
Collection<Constraint<T>> getComponentConstraints();
/**
* Important: must also include those constraints, defined on type
* level that reference attribute as target ?? this would
* potentially require existence of a bean instance (which is
* assumed for component level constraints anyway)?
*/
<A> Collection<Constraint<A>> getAttributeConstraints(
Attribute<T, A> attribute);
<P> Collection<Constraint<P>> getPartConstraints(Part<T, P> part);
/**
* Explicitly triggers validation of all constraints defined for
* this component, its attributes and parts.
*/
void validate();
/**
* Whether the element itself has validation errors.
*/
boolean hasViolations();
/**
* Returns the violations reported for that component. Includes
* violations of all component, attribute and part constraints but
* not those of nested components.
*/
Collection<ConstraintViolation<?>> getViolations();
}
Interface Constraint
package configurator.validation;
import java.util.Collection;
import configurator.model.Element;
public interface Constraint<T>
{
ConstraintDescriptor getMetadata();
/**
$(G
* The element that defines the constraint.
*/
Element<T> getTarget();
void validate();
/**
* Whether the constraint is satisfied (valid) or not.
*/
boolean isSatisfied();
Collection<ConstraintViolation<T>> getViolations();
}
Interface ConstraintViolation
/**
* (c) 2012 Copyright by Vivian Steller
*/
package configurator.validation;
import configurator.model.Element;
/**
* @author Vivian Steller
* @since 1.0
*/
public interface ConstraintViolation<T>
{
Constraint<T> getConstraint();
Element<T> getTarget();
String getMessage();
}
Interface Agenda
package configurator.task;
import configurator.model.Component;
/**
* Represents the main entry point of the task based API.
*/
public interface Agenda<T> extends Binding<Component<T>>
{
<E> Iterable<Task<E>> getRootItems();
<E> Iterable<Task<E>> selectItems(Filter filter);
void accept(Task.Visitor visitor);
}
Interface Task
package configurator.task;
import java.util.Collection;
import configurator.data.Domain;
import configurator.validation.ConstraintViolation;
public interface Task<T>
&6R9%R89 &+=+
$#(
{
// structural
Task<?> getParent();
// task
String getLabel();
String getDescription();
Domain<T> getDomain();
T getValue();
void setValue(T value);
// task properties
boolean isObsolete();
boolean isOptional();
// task status
boolean isSpecified();
boolean isValid();
boolean isComplete();
// validation errors
Collection<ConstraintViolation<T>> getErrors();
// visitor
void accept(Visitor visitor);
public static interface Visitor
{
boolean visit(Task<?> task);
}
}
$##
Bibliography
I&'((;J&13:20%B$
"C""D .>% :EEF0:EEG/% >K2
. "+2+2'((;%
I&'(('J&:&E&E82,2%8(
%2'(('%
I&#GG?J&E3-8E2,%+E321%/%!-
6=--*
7*," *3 4)%!++2
#GG?%
I&#GG@J &E-3&3E2 , ,"2 0&E3E2 9 42
,8-43E3E2E0%8+:!%
H8-%#GG@2%#'?%
I&'((;J&>&E3E24%2,cEE4d24%28EE3E24%
!%
>%$-*%
9.%9H/%'((;%
I&6V0'(($J&[3:0&0E28 % +
> %"%'(($2#2%'G$'%
I1b'((<J1&-4e>2-%3%2'((<%
I1'((#J13E3>29%I!
$%2'((#%
I1'((;J1:39>3-24%2%+ "*2
.6%%'((;%
I1'((<J1:39>3-242%"
% ^1,2'((<%
I1'(((J18->32-%+ *".
!%#%'(((2%F%
I1!'((FJ1-8DE29%% %2'((F%
I1 #GG$J1E)3-2&%#)JB!"
%+2\2#GG$%
I9#GG#J90:2+%33-902-%4 6"%BA
%#GG#2%;2%<'?F%
1 "
$#'
I'((GJ&&,2+2%&3+4&!1+,*&-
-"%3.3&EK/>
*5"&D>#83.#8
3&EK/%'((G%
I#GF@J&2",%4%&D"2#GF@%
I'((<J 8,90>32 D 908::2 &% 1 - 3
%)D 2'((<%
I3. '((FJ3\&)--32%2%&9+ "
%>%%'((F2%#G%
I '(((J3:3-E)2&%2-3-902)%3%2/&EE&902%,:
! "%
",%#B#%'(((2%#(2
;2%;;GZ;@(%
I '((#J3:3-E)2&62%-
%2'((#%
I '(((J3:E)2-"4%!%-7%
!%"922'(((%
I.'(('J8-\&29&:&8-2.%, "
7*4 "
%",#%'(('2%@?2#2%F@GF%
I) V3'(($J)38-)3:E3-28-&!)0%> +
1%"%'(($2#2%$$$?%
I0'(#(J0&::3-1&902&21&3-242-3903-42,%9
"1+,*4+&%,%
#68%'(#(2%''2?@2%<#G<;?%
I0#GGFJ03E2)%280:8E2:%2,9>3EE&2/%+
C %%%#GGF2%#(@Z#'?%
I0#GG@J 0:31-&E2 % )% "
6 - #
% 2#GG@%
I0K'((#J08:40d3-2E\:e)X2b%6%
%&:10E 2'((#%
I0 #GG?J08,1-)29%D313-2/%+%=L
%#GG?2%?<$Z??;%
I0'((FJ0&,2:2,8-43E3E2E02-2/%
% 2'((F%
I'((?J 0:2 9%2 % >. , 9.* 3
.1 9 +.>%-;
%'((?2%?(2$2%#?<Z#F;%
I '((#J2%"91>%2'((#%
I/-'GG'((GJ>E)2)%,%8:KK6)-"2,##%2
'((G%
$#$
I/-$($'((GJ13-E&-23%+343-8E2%/-$($*12#%(2
-%3$#)1%'((G%
I/-$#@'((GJ3,903:2:A%:B%,%8H5M6,!"*$:DE*4
8%/+&+36)2,"2'((G%
I/#GGGJ/80E2%)3>32%8 ;3%2
#GGG%
I/'(('J /80E2 % B 8
D%2'(('%
I/VD '(($J/83Df++E)2%D 9 )0%+6
+ %"%'(($2
#2%;G<'%
I/Y '(($J/g-)3E3E2>%&%,- +%
@>%*:H:F,:EEH*
;-*-D#%'(($%
I>'(#(J>E+:39022%83 &!99
1+,%:K"%
'(#(%
I>'(#'J>8:12/20f1E3-2+2-3903-42,%&")
9+&!"
%:E""%%'(#'%
I>#GG?J>840&2%.*4
E1"9"/%#,%#GG?2
%#;2<2%;;';<(%
I>T'((<J>-&4890h:2,9&-8E29%16
)*%!%% 2'((<%
I> '(#(J >-)2 &% # 1 J %
22/2'(#(%
I>#GG'J>,&-2%!%!%%2#GG'%
I>.'(##J>fE\:32-3903-42,%+0:!*!
!C! %,%
#68%'(##2%'$2;2%'(<Z';;%
I:.'(#(J :&E\2 &2 D313-2 12 -3903-42 ,% D!
4++!"%#*3
*"%655">3-%
5G"#%!-!%#:E5E%'(#(%
I:'((;J:39>E3-24%243),&EE2-%290:9043-2/%- 6"
" .
%"#*
!%%'((;%
I:'((?J:39>E3-24%B>B
%32'((?%
I:'((<J:2/ 6%!7!!-3
%%2'((<%
1 "
$#;
I:'(($J:E3,&EE2A0 %B%
D ! # :EE5:EEFD %43 GN:D 4
,%,2'(($%
I:'((?J:E3,&EE22 -390D&:2-2 \c02,%A%B%
"OB)P3#;%
2'((?%
I:'((?J:E3,&EE2%1&,13-)3-2)%+%
:E3,&EE2%2-390D&:2-%2\c02,%%"O
B)P3#;% 2'((?%
I:'((?J:E3,&EE2%1&,13-)3-2)%&.
+%:E3,&EE2%2-390D&:2-%2\c02,%%
"OB)P3#;%
2'((?%
I:'(#'J:80-,&EE2,-3903-42,%3"!1
+, %:E""%
%'(#'%
I,#GG(J,&03-2,%:%+ "%!"%#GG(2%##2
;2%;G%
I,V0'(($J,90&3:0f::3E>-3,3-2!1
)0%3 + % "
%'(($2#2%$@;(%
I,'(#'J,E1-82E2>8:12/2-3903-42,%4!
"9>! D%5"&>!
.!&5:/*3&5:>%'(#'%
IE"#GGGJE&-3X3>2&6%%%%2#GGG%
IE'(('JE::32%# 1 #
;% +%% 2 4
,2,2'(('%
I8)V&'((;J2%9=6 >%8)&2
'((;%
I+#GF'J+9842&%4.8 %-3
%#GF'2%;'2$2%'?@'F;%
I+#GGFJ+::3-24%B6- >
Q%02#GGF%
I+'((#J+::3-24%D#B
"% 2'((#%
I+'(($J+::3-24%6#B
"% 2'(($%
I+'(($J+::3-2484>829%B
D7>D"+ )2'(($%
I+'((?J+::3-2%6#B"
% 2'((?%
I+#GG'J+E321%/%6 743%0
1-!+2#GG'%
$#<
I+#GGGJ+E321%/):,8-32/0% #)#6>"
R#3%%01+2#GGG%
I+'((FJ+8:&>21C%B1%
%)20D2-.!
A0)B2'((F%
I+#GF(J+8-43-2,3%6(
%+2#GF(%
I+#GGFJ+8-43-2,3%!6%%
%+2#GGF%
I+"'(#(J+-X2- 2%4!6+,%D
!%#&5E4"%#%'(#(%
I+'((;J+:,2%#3%4
,22'((;%
I-#GGFJ-3903-42,&&,2+%&3+46 "
9 D!D: 9%,""%
*%">%%#GGF2%#(2'2%G$#'G%
I-'(#(J-3903-42,2%4+&9,1
+, 9%#"%!
!",%'(#(2%<2$2%?;FF%
I-'(#'J-3903-42,D313-21% # 4)
!"%6** % 2'(#'%
I-!'(('J-390D&:2-%+::3-2%4%>DK *
+.%>LB*>*%%
'(('2%'@Z<#%
I-!'((?J-390D&:2-%2%>.
+%:E3,&EE2%2-390D&:2-%2\c02,%%"
OB)P3#;%
2'((?%
I-!'((?J-390D&:2-%2%, !.
+%:E3,&EE2%2-390D&:2-%2\c02,%%"
OB)P3#;%
2'((?%
I-!'((GJ-390D&:2-+::3-2%">L6"
*"4!%) 2'((G%
I- '(#(J-3EE313-)2%!*8%32
'(#(%
I- '(($J-8)8::24%+::3-2%4%BJ
$6 :EEHS %* #
%B%492'(($%
I- '((;J-8)8::24%+::3-2%+ i
*& ""%"
#*
%*-%'((;%
I-'((?J -E432 D % ?!% # 4 T %
;TB%2'((?%
1 "
$#?
I#GGFJ&1E2D3)3:2-%4!
%2#GGF%
I'((?J 9033-2 9% B 6 #
$ J P
%J%: %2'((?%
I!'(##J 90E33D32 " 084342 +% 4 !
3"%2'(##%
I'((#J9002)90D3E>2%)P6%
%02'((#%
I!.#GG?J90D&-\3290dE:313E2+%
$%0 &)2#GG?%
IK'(((J90dE:313E2+% " 96 %
; J%
2'(((%
I#GG@J4,+4E3-2,%&!! %!
%#GG@2%#(2'2%###Z#'<%
I'((#J3E8E29%/3E3E24%4
%>
%'((#2%#ZF%
I4'((GJ4&9>2)%%2'((G%
I4#GG;J43-3>82/%,.%">%#GG;2%
';$2#'2%;<Z;F%
I4V1'(($J 408-43E 1:39>3-2 0! . ,% >
+ ,9.
%"%'(($2#2%'#';%
I4J408E3E2/%2%D9 "%%%
I4#GG@J408E3E2/%8EE3E24%6"%
%%0"4 "2#GG@%
I4#GF;J48:3-2&% >%12#GF;%
I#GG#J:-902>%424E)2>%2,&E&)3,3E42%
"%"-0"5KK5D!
%#D-#-./-#%#GG#2$G2
%@$@G%
I#GGGJ3-8E2,2&-)3-20jk2&:&E8E82,%4%
%2#GGG%
I\!"#G??J \D9>X2 .% # # * 4 >%
>2#G??%
2
`0!%
2#$%& '(#'
,*<$G#$'