From 45ebce9c64c4608437d381d55a57589518507826 Mon Sep 17 00:00:00 2001 From: Janne Valkealahti Date: Mon, 6 Apr 2015 10:55:54 +0100 Subject: [PATCH] Updates to docs and samples --- docs/src/reference/asciidoc/faq.adoc | 6 -- .../reference/asciidoc/images/statechart2.png | Bin 20635 -> 24092 bytes docs/src/reference/asciidoc/sm-examples.adoc | 93 ++++++++++++++++++ .../src/main/java/demo/cdplayer/CdPlayer.java | 4 + .../main/java/demo/showcase/Application.java | 33 +++++-- .../src/main/resources/statechartmodel.txt | 83 ++++++++-------- .../java/demo/showcase/ShowcaseTests.java | 29 +++++- 7 files changed, 194 insertions(+), 54 deletions(-) diff --git a/docs/src/reference/asciidoc/faq.adoc b/docs/src/reference/asciidoc/faq.adoc index 5f00a7ef..d0b56698 100644 --- a/docs/src/reference/asciidoc/faq.adoc +++ b/docs/src/reference/asciidoc/faq.adoc @@ -21,12 +21,6 @@ There are few choices a state machine developer can choose. state transition into a next state when state has entry and its actions has been completed. -.How do I defer an event - -{zwsp} + - -For more complete example and explanation, see cdplayer sample. - == Extented State .How I can initialise variables on state machine start diff --git a/docs/src/reference/asciidoc/images/statechart2.png b/docs/src/reference/asciidoc/images/statechart2.png index a855d1c7da87cb4e584e490d26677efbace0352d..aa407e930b4a1ebf25fe2790df2a155ece1bd937 100644 GIT binary patch literal 24092 zcmbTe2|Sc*+y<;VrPWrbY-KG%$Q}w&)+|}FbtnqakOqV4oDw3kCD~HRP7=nRvV>5` zI>^{UM%J;8@Bhru=`8R2z2A3!zjNx$%yU2Y`d_Z=`riTPb=3FlJh+pFhGx&Xv#RSiR{O8FzTQ@G*$$ z_`6*D@!K_3y5?Xhg+#ZTPrlyemM$j?<70~o7wuMJG^Q8Jw&x{u<)ydvI%JNRMOqZ+ zuk3~nJss?{W`#d#DmmakZylIPYxMA!Qvs*(o8V6Z9sK7uZVUXE@&g(aE%NO@zdJ;P zPyhCv&Od+h|LyU=Ui+`68PM=5YM0i(6F}bn)|QDRjP!zRrD2H2!YtFAe={L$MkbTW zb#-;u2DsLa?Ay6EvbMrS8C1kG+}e;Rc5&QlZKh2?}Q77oEY6zWifhFF1+?~Zs*IF zFBgUIMQ-D7|JZV+>FV|C56;N%q4Afe`Fg#jrDdkCFmUr2>o1C!a0I3c9C9L`A8$#79S)PWS36t)3v3-kP}hT1HWkGf?bm`6guH zN-hWr3O>7r{ZT<%T3Y)4{rlY9+?mPD)YJgXE??!>`=za?;?TW0eUzE+6;x4CDKvMg z$A)Vpb#-+?Kf^FKsMDGuRa*Qu>kVEX9v)UxR}bM-coHkMcb~2+EEBSEl0MXi3yh=} z8eE~Yr4g#yklX3_`mvX+o1^0~(-o_=aqOatAPubZ+k>AvI%JL?XE6BC)YKSVJ2Lb6 zJqCjb$G|`fY-)lZJ$f|g@({)I%ShQ}U0#%xm6ep7jMPYK871{$%gf7^c9-Ga74-RF zzP|nAqr^osGn>ykl$oJ{w@`M&&p%+zZsRCRx4!GCo1${{N)_dRc)=#PQ@*x3i7c~I zPm!deBAIJ#ifawoaE?yz?!SNV{^9%Z_m4Es;FFV+*OuDLt78JzR+`p=+DS@qq;5B8 zo1k#0{Vwh<9WJT<%Sz;_kn+_D=RWM3cgbsa<0+WFzy0X7E3#8=>kqip8WLb(`M1~o1@L@T;372m#yR4+S=gb#`1y>D;3ev(M^iW$6^|) zr3P}uT&4(B1Y31AHS5cLW!_bxutXgTczo;|#Im5Q{&Z;1O43jLG?ki~+S%C&OItNh zOG`Uq=Kh$px=ebX))cQ$dE-p^YWodSl@PWL# z+}+(h#12jRFE^i%maf?r$n}hMr>{vyW@emof1l6t_1F7}oPmdznwUu)R#lZ=O_A+-iCT1HKR3U=1+MDcKjHH~aEb63ULR8_AbYG!)m{_>x8vL4fyr+DTEw=BS5 z38i98O$*;X^T;Arkx+IbT8m!_hp!#V*2GWtm2=r!T3K-w(6h@h2zgCau~uQAdu#^} z@=|;F`pug+mD^xWdQ)(;wDg=oQ$ogBcPna&eU%d*2GwBhO;1mg$v!)%Z6A|%!XFV5 zN>5KOb{)|?bz&dki5GsG~}*w`2l5OCrC^4G7Iq+%?*WIymFq~zyI6_V;Ag{mrgdwb1A1iE2F zr|_D-Ey=n9Tt!V>8QIxNp0g>Alm!#r0f$>oPHxzWmlJ+>h?sQ7%*>2GymrVX134y@ z-q+_p*Re*Q`$i;YrKg936NDe}39oN3eZ)CdmhMwfJbcS)cW`j9#!>iyffQxu>GKxVL|Pu0Ako{Yr+Zz~+TJ$Kxv2Kac5qowc&Ea`Y@9#`uqF0E?>QZQo@qG94Dab(>su{t`5~+7SE}O)IFu-I;@pp zU|_Hp3wwH5nEpj~`e) z<>BFh#g<=2q6rk1&k2vyGcqzVHb%oQO}thXP>Ko8_VyY?Z#WW|$x_y)g)hcdRn{xo zjkgox<1L$8k=-J;Psx;>jV-XM!#j-HzYEc^v5pQ7=_x7x!hRm;Teozyw0O~OXmrgb z8yg$c&|rOrrX`*Des=bcwz(U7B%IP|%_mDsOV0>DV}wIQimyLJbPytHlG{eZ26}pW z+}zx%idnL6j5a5sdp!gqHLkxZV5y&YR<+VkkM)gLwlU`4WheTUno^D6 z#TI5qTP}+^Ra)<6G4`Lc;pHrzCXY-(?<&17K<_$xd&$c5i;Lw-cgaNelfW0Yx_%rLN#IJK?Q*z-RG5iYAAp*LsmxkC>~P*RavKz znMGD+5`+c&7w5a3!>e#&Ya_8nWoWTlXC>xxyy=mBVF@S;7Y7KmE*>I|-t?55G`UZ* z&F!pmco{FYc5HrYaQupawXdD&4-Epx*&v8tC_b4$_Ci^Ctbp zWz-?uv|8z1E6uD0ChIn?JP21%P#}HcM9C+W-n%#f`?9Y*6I)4Tu{dcdsp<(bnatPZ zV09xHbHqm^N@&UZ+p?FssMF!Yve@C|1Ro6+@b;{+`@_8mWis}N$A#0Zg;$BFudi3J zw^GK3w;10Scy!Do?V}4xr1v8D(IEKe*ntmq$#uNOQKA}a6Ws+PeZ^meRZCt(HihWk z#kjk>ll_Kj{ib#`qI9zaT^FZ^E~BO{TnTf<2hNw{8wV*XzbeZDWv6Iiqx@4i;f3W^_t--!?Sp%HoD+@um9M~*` zbLtf%30Te$InUW6NKAZ)n9WOsNV3qJ=*#)~ZO{8KiD)gkI44I(^BbQZGZSI)fBGbp z@r4T)?Ck8O?1Pk)v=Lcd>!ql>dk zWG!?po*1sHSZkY`W4kgjHYON9peQc>dO?n;q_jNL8lps&nF)fu2Sc^&al^k~h+2;0 zhtuN7g2IZ-&CTsnq_-4JAeRlbn?n5KT()Q%Nq>~=GDg@-8Yy2GG+69g8J4zZqU;Wu zXb%R`VyvRK+aw z>wzYG{xib-k3bV~pFb_=x*>&+Xi$_a=jR_tP~b05$v!CN=^yWcZ;_WcZu-%e;zaZI zNz<-M4k13jI2y+f7ti<5yy7fAg7Qn{KoTf|4xW$iDU0fFG)0up&hO&hO!+YBITC{- zZwzCid}tAYvpH8(R0LUywLPtW@%x=Lm2tQz&-gE`t>&ekUs~zbf6o_Zw?jZD_HlHy zSY8xAWD)|p@%TIkW4XA-%i^7m`KhVb$UFD$-P_R6z&7po$BCVXK+q)%rHygjKt%E|{hu}*zurHP5ZM{*MbzVCG@YyIU>)oSmJmY-}2t zadma|Rqh|pE?2zq_3aAt#ful;^#sT_Ff&Ts$aZjYD)U-&3G&OvE{!JV*k(8<|AE^} zVoG}coX5)>PMW8u-0os96<3;k^icHq*Sl}ce>XM2r0Q8(a>`>R*O*X2SF`+I^<#RP zniOL~ByGIq_aLL^hQ3`f!5qP$cz4SilIQMYlpP$#@6gg~O(dzDIdkUw3ccdOQ!p&O zg~Fu1-w8UdXYMw98vhd_T@#7$+Ky|m*rodxf4rxMNN_mhZl$r2QP~dYfpecv|GTXQ zn1JIaPDIoX-B$;vnU|MWRdNP@4LY&|W5FOcMy!k*zP~-@MSE4LSiDYhO?CBmG0KxCPMpA(c({^3 zp!>XyEi6{YYA|9`=9=*elSd-9!_t{gV=F1ovX!;-SzXFZNx|Kkcw+Gz?1!i$Sn^DQ zN{iCk%FG}s>|GZd8=G#d%#>%9_jp@ovQFGZV&Lgu<$&`?_7O}j=bBQ6ul;4*XC|hP zx9{AQiBD$&FsXZA_kQ_u!PN8shKE-%!<&r0U}b?vPxgARF1Zg)ixFyqNbjDXpY{Zj5F;~F#4dO9 z8w4aTZ{5bpXMjZyD1Px<>!1EKZ%a<$f48Sa{)!y4$6cG?aKl1c=x??^txEGWkO}!L z?`hE{h0{2)l|YwJyGaq=y8xR? zQ{$Ad|8|<2dIUNHdCJkGe5k(Zzt3wL+b?ZDW`+0kMVwnan0>#ir^mwBcx3ytS%?1N zh8PYGjzV*hI2}9j=s0;ar>u*rTe=esdjQTRS8IZr`UM}-C}ANl)F@RyQo%z6&Kd|O z3SwJYI`;ED@E&z;V#huM%nKJJFKlI0J=(4umXev7nP%p;<+vyVI^(o{a7akOn>P`W zk&u2v6iv5hkMQF{QH!G4&+1%P#G_3FB8G@P#WRx@KP2AOPW<1}L>_;Ar%#Z;`=-j!V(pJUKU4LQN+@(Sp6R9E-(Zir@P&Ie$Vjq)z3;r$rZ}X=XN~ zYPxmmAm(vDJ7tr9JdBb?D(PaECkkq0{o9XmGKajc2z>#Tm3i&C+wKd_9!n^>9u41 z`vdH}X1|3}Ix{}L7yV@qVq=|CUVOYPKJ{=&N6Fj5U>Q~RV%%YcpL5rXr5srz;vG}H< zcdZ-wX07Ba)*y93`CBHed*lj(0i(gV5ZzrkNarsj%LQjCSUNs}>hNo8i^VQb6O0TO zdoD^s5h%L9U~uo3wl;oJqf!fEEu-pXZS&DHk3lKk777?wJjGpM4o2ubTclxpi zIaL`UFUn7+ZK8jH?v9iL>e$%6+i%DZKltvD3aC2PO$a<2hcJL5!~fe(Ek_>SI+Ti-2ydzMo(jxJ zO)d1COB>sUcuK4HL30q8gJqI1ICG|Is6L8sNOR*vUEJos9LBsaRt9BlYpb^Y9yyz> z0N??<=))g=l&p+A5Xtf`{Egj+$! z3ZAn}7978~A3(jOt^Uh`RSF#tLHX`tr7j;ij8Jx12@>wZfk}rqGVH282`)}f%iq<7 zdz~Sx3dscLcDDS~xi89Bt_(e5;;;0+bmZ;@}|1i^Ovoz`sv5Lg4&9>+wxmtB`nijUl;+MphQFF-|^b0dh1i#lF_o2>deaq3tL07dP_t&^XA~T|~0e((YG1 zynPu3=qL-1w&X4b5+G4vLbI*Pv#7fxDpot(N=M#6Tj?wLlCTw&ZadM?3WUi;y;*q=rg zLDT|O?z6fCJ=Io93Xc$4X>I*;ih77J`wz};%OWmXJ&G%Tm!uih>oF2%D416?txtWgDhm^OW()-q}`PNi}?)>X5 zxoxAZRB*tCUgb{j+b^Z~Uoe91r1Z{o*pyRcd~LDV!jI?Y`&NnQ#7Srr9HSTx@JC~h z0&wQp4{)&6ixU$o{Pv8a?L!O$t3H3$Tkr3eV)9ESQip6#7a*Rq%4`91HY)&`RYDv+ zehyE&Z5zv45$?OGl>r9ODO1zVI;D#3S3ixH7Dah|aOuG~I%eeLfc1!yJ>;ws zii*9>%}hec8=kVEoCLWoc(Z7&Vc39d?Ch~?8Z70*TX||jENOFw;4Fm;=mJC_VmY%s zSw8vwdj`bIUtV`Qs;jF{HAf>jbIC%~m4xC1o7MdxHCZKPvW$SvaTDpe6i?p#_9?7< zR2b9N-daXI#Ko)!XREV_UjSG2+P)eHQ$96NqqI6}fPcKETNpWM@exoH{ZvDUXj@wi zP3CfJYOGfoW(RwLa45p%9qQ~Ft5WEVuI#>7XcsGw79k48&q-q&yqD*zCIVX`}jGe;!`T2!gb@33Bl=8B@9$O1O=w9^dCHihF%}K}1 z5qeu&_wi6MTj}Ao*p@ny2>;?lG9b+S5S1KWJkZWpa0{Z$tptc>jcuB%Fu9!oq8Kzi z#{Nx~>*=RvaVKHEQi1+}_Z((5pA=6C4 zGu%*B0#3lJyBO^ZJkwPB>x5;UONAKL^3+RXa0q$~u9Phkiw9lzCE&8hQz0dW9HycS z2HBsE$*fe+n;BAU_F+ajJ30n+gC)_7Z!i1GPCCD0E@B*;tlSq~9Hxs8G&33U(NRQM zvFDv*03a2Pc;6bCRF!^;iR31oS7Ue)vXqv1?_GO5-y4$x;{^>)=3K5dxbmnN0078? ztPvAdd&)@h0)JtVm)??dUzx&M?^fr-1inl!A1`h^5I!?X$8;5gu!U4`VQEL=@9J~xLH6&$t035z_ zcAAzP9B684tiqCd&^88#Nhl1N1D!d!%h}Bvqy*(kk|t0quHrqM3Z;kp7F}?Y5a&Q;JO_GKo^(~ zEv?P!uI(GId2ZBO3ZWlrd48fBd6Z9(ct{8mjnC=j6|cAuZ!dCmQ{EwN8YDtT@)Gzf z0x<+{M)0Cu**9ij|LeJa0>-1=Yu{!vYW|1C+1<8$enFfW%*E&utM6 zYN|wymDZsKYOWNM%i`2q()sx_;Oxz#H~GUm3tdM-dDNi;H+YfU=e%;>j~XSiSUx+! zXR^1{n`*HIi7Kja1vhxtDPYvmy#R!MN$jm5%_Kyu5X(v`yJ1 zco|S&!vcRA3q#dPj+lavUa$IFo-}7~HI8Ite0xMy6`%M~tN%61`y>Wp-ud}?uuW7-pQ{R(5_O-Sbq_VaQUWBP;9A%Ag39 zA3uJyy~^;v0yOm&yr?0}l>rCryo@Cz^j#1|%5{y5pTQejE!#er>u9L1sgakH1NxZI z3jjhvcD86+-;bUkJ%4}P^Sfcw^`hk~5JeX__W{rGLzydF2|Y~*d6_G0*FAlQJUu(|ka6B;!k$YUMkq z5wP^FJ4ZxCLl}%^7zcKSGLZ^?eBZKVOJro^_>^6#)$+LcOqaAn#<}(wjM%FMb)9`>R#=)WuPBBQnN zn*E(zieB#DJ|*fe`?lwGB_y4PNptII*uZ}n(3F-7LLwxvkT?Rnwh$&TS^`J;(f~ zOnyfUYaBB91J`-4d~69^<0=|@z!*+?`}VEcbp~+8&z}QB!l_OE%zjL!Ar6<_pS$i7 zwNi6lOPBZl)g1A`)J-`BDJeDl0c2u()%2zQ0TuBpx&@A0?BCtB=aCWxDN_1S>AfdG z!KK(eXIBC)N_iqivdvjqv+V6fJw4P!S6;)X^+n=7y0$W+RAaabW?i5>nn?m}V>1x2 zSHN;|u+(k5%^+DPbLB!ZGz+etyUsSZva~gRl~lgwJtg=s#uTraINxw^{7ua2uypyk zvhbqVyuD}zb2y#Of=6xM5y!?f8oB)gPTCR|`;0MjwQvf0+Ow_te(d3XVRz}$p`Fts zc57D}M`jrHoSj8cq7`=K9y7Mn#hNiIY2pr+)Qt_aRv7))Z1cityw)p;xf^gkGwz5B zHR5YRxU7aI6S7GwvMz&Xy}i95i5861NTy_TSSP9P;0OdnX?PMR^V# zB62e^KJ^Rq$KAoHNYx!-+;lz>%)O9AHhX0cc^@MUJm*kRr*(%0#TuGMOEFVYB{-Xb zL>91Vo0v850rFB$aq?cT_0$5^n~nB>X6Nl{&;0fls~sSZO4hKH^)EiEu1aHg1c8d1 z?VN7}7yGOJc6=wym*Yhgdg1c(ASOl{q_tx4nYz>X30=lbpIiZ^GPXVVn}4ytp~6$; zGphL0`2NQ~`>3h$OCMFDBRhn!4~*qUsdTbij0V2_$C50+ULO7NofH5Yg*}&+o{sVK zyxhaT5B;UIw#s5cg`SlWMT@f14M#^mV9lgOVq z@#c~fLN)wT)PSxS-SdCNt1@_qY0H^sUd&Th=3HUCJB=Wn=62a9hd)w0qSqFcCL}`GsAI}vwT6*w@2Si56SIoL;_mU?2LPiVA z$`qZrWNsWX0?TXqydK?o#_}#^71Vy)#aVi%+WwOnyaDKcAtx$j4Rh z_wV#o7U%3eZ)w@v*C*QNU%a{~#iPGW^?^vQSE?VdUAb}vC}%VgA5aCS75GRXBQG>I zK-`yOa?-}lw-&OoW7WV84mhi;*ZetkL}^hCKhachAhe5m=Jl&bpab7>9 zu&>I>$lpFc54-Mqzj(Fq95=Pki67fqgc4$6#=m`gj7_}CfL?Z$Ko$Y!P$fDu*|@i@ z?NRMzm%`ZS%S%hv1NEz?cr5G1IQH*P$;dD#GQ9n(bNNK8^#ejlHCurWhg@^m zY9;af5#HQ62n(&n0CYhT%O`;XlL=9at=GZP0p{5}x`(3$EF-7f&8zkL9h8ZoOubO< zgPA&j@oa`58e_2=N6=g0tQ!zUa>(BrbSX4RPD>MXs`=oOJ4dLMk3FO|y;yS7b8pQ} zcXye^O_~HJChyPwt%^wO1@Uuxr;u)POQ5glPb|vn7`=h{4^<)E-k(sETxo#KQnJ$O zwW$N*XZ;mym@X{SJV!#^=j{iMY*|v z;&ZdUZN|TBX;8)R8F3ysVCv*+R^U|iTRCv9z#uKK6$l6j7|VM2?FEV)xQ+TGX>Tp; z+HxOj_U3bV?PvB}>xP!?M`Yjs20W2^F{1hN8_?6A6zC~mr?DXTnj%#xazwarmL+(! zAx1j9&w`tX?7xj^UaW&oba!2x=M0c?6rktB~z$yH!^TgxEjTG*$ z<|MLLs!||^)R}R2sJRLMfF9D*|D55(mW`PBd27h%dS)cwz`OI5FB6)O^|8c7=H+~{ zKMl205_>iWr>-7VpKj6u=tXU>1tZROFkWeU`i!A`rVZQw&$;3HzSUd;>=#m*6EGav_|l($LrAa9bDj9 zRZ%X0WGQqq4|mJ3~0vdE-2lNY{9=MCua&kP{f#bgDV5h1Eo5P z1mfen=36;$B#UN7<&3Wy%Mmu zu<_sT^421oqv+Q&f`(h{2tn)r4b-L{#L65n!fD9N8QW$X;O%T}t$D+1uL1<11+ zD={$vFu2IyW%CMb*)CR*jJ|=#p4EecgLUauF$uiA*fkPXfJoUq8fWo=fw~Ebs{lva zAlN4*SZX_?+W#%E{3H_86BLghf8`TmGaZ0&(HQJ4#X$T6S%lx#@mN_`ep9>J+&lio zJDC|#>gW71$K~bOc)%@gv;v5Mv~zE)(lp2|E*Kk^KbptgcF$sNjJFaU!J*yUkc8uW z;^d6+!pclj_>`C88k4;a{){%ng#Pkx&Kd;!KN@brl3lNQezTp%ocn#^!Gi}t`n#7B z%GTp|FN+UzZtTyyVTnW+mPSWglEdB0m&Veg3|t8!$nKwdR9Whtre$ZByloRfR-vKMFt61N+Ur$#{%WJw;pwm(6 zpwG$!>62Bi_$c{IY~fLx(BAInzn?i7I}a zie4%0qqfgj7*REHBDq;vSr^Fd9hdppv}L*VS#PweA}tNSekA(*<;&r*FX>&+98U~o zjQhu9lyhx(?bRo=XFz=gDI)IKGwwK@sL06DnMQf_VD`{-BzmZ8SL#dv=4eRhdGyE2 z&yOb0R`rN68^^dO^Z%_FDK7sC%=5@<1-&v&MIo@=;ZWh{Yf|pKp`0|2s4F8 z!%G>^ZkyDvpHov)Bcy_@9u$ON{YkwU6X_D5=bB{x{8}xkCocZQV0!Y|kyCwguA}3z zIg&}ZdSD3gpSrr1fa#&OMbZ`_nuKJW%SRv;1JIz4K7;NWBuPGw-q0=Jkb#P#NJECv zsWF+gGcQ|4nSClWvcOoERfLN#W==}-B7DtTn5@yynhbNrMuf6Zm|hcgb>YRz((^}3 z8s6dGG8Y*^8WFJ+@#;k$XtOeY2wzy_VH?%E#;J>xisKOq$f^5x~zk5h6NXB*otAgSlZ+pj%xMiRtcN*>ddNS_%|ejjhPS_Z!=)m2=)4Do!b zp&&)I4|o8P=v3niDOtl%UTF~Qo~q;_SU( zJ|w{*`GJcN{GiQzFvKxJ&jby`WahNvDVV(9TiQSvfbz2ue14wkoFxU|`NH(^WBbDD zT`HZ@v)jF}O8_?J4XrEtG`MT`>cqUvl|@nZGKX6=X!U39B6DLZHNCY`~EZe-x-p~;=5sbaOht1 zopx}t@(+YO2n}QvWs#N_7iZ!DutzAE!bXM*`H$Pa)olIQ9hY#l^7dI!%vdT&WLp$J z(nzv)_(zh29Xmb=gudSezZ1t8hzQ=!lVf|5_kb*@Y=hY0^x$+rKNbY)tRk7$RBD6v zV*WsqLjq*J@5LhZj(i66hsrNnib+tSLW18nfEHLB92`cJ=Abwr=GeXB8f$;DYn4Jt z;=d{VDWk)thn*@_AWGaK+&$Htr%Op#%bIgRu;a9;cfXhi{qEf*))seFM0;KS-vr}5 z-wVgT37Y&h<4miqnV@a*bxzAvlmMw*M#=v!Bj;hKy{J@?{_8A~p!h^LPA+dcuiq#k z8W{haX~2`%m`OjAr{fFm1)#(Un{scWW>1r+#s%CX|JphZ)8Isq(_m#|`#WIWILE>Qo zWFH^^OW#MTsHkw1Dqe7TsHvz23J;e_fLib0p(qC%_1biQ++UyQx+4*)VSc*cOR`BH zPkJxioK9R`sQ`!uz%04Cr5%u&lN4edmx~@4m)L#}aG!M>;N&GQ9?MK-zJ?01Uj2OLF=h`8!$Vy28j2K+fWXVh; z*c$fd%^^#LKc($0*@J@q@+VlY>q*t6%yE1!U#TyzoFPNmhmMGjxPpQ=6g~_O+tyrt z?~j3mR982|htK#lKC$p>Ab={F1OA9XJ_iPw{rMh-xiA9fLB=}(&@DxpZ$ zo`3^|XnAR=MQ&L7A>t?VH)lG};@i=x!1&iDESUDAy$n|!f{F?YWsLxJ{@2s_W=@3GAgs>fspS}kkIZ{c>SgyEzo$kv%QFq)Vq&3Qt2ypnCs5cJ zJ&-e1*75N0)MwrRy7A#MP+L0M+Eslx1zFib4WuZ5DgqGHM7$dvA?x&8v7YVAGr;Fh zl|YyU0{U9@^233Zs}ri;|1GOAaG3;rrw;`C9bLv&-po+1AiKo}0`PMNl+!loxpJEQ zlgaJ}=S^KA!Lcx)A;B5l)|nvIf-uB0}tPQ_D&q>&H`(uPFgfpcm)P0c5vXRK?i19e|-$UnhS1bq?ccYj_DY z;u%wx-a9uYUCawjJBR?KBKNg{-{T!1y|%Wt$RlGHj2d3b1y^z)-#xussnC&Y*92PV zFGzC`B%a0}X8R+Ig%YRi@+mX4_-2dbD%773R&E66$a^HgO(W6SsdIst_4qnv7X)qT z*$1H^NmhvWo2nsW5`KG+hoTk9mMF+_==~%roY5~pbeQXATyK^)%u5UwPRL910=(|l zux)q3&lhfpJRrJ&cjih!90ATbmCi&H)kig+(DQ8@9dBk{j~P^NIho<4n7&+bFizK^<4q29EgAKfl`D<^Lcf*}ZC3tCQ5XT-R!mK*4R zj0{J>K@i0R=+s)bTGs0oQ#BVHR~RU4(pO1;3~CB!Q&9hjHMg`p7x{5t{rXScME6}| z?M=u49DnQ0z|n$7RI976|FYF`D5Zy@gZMq%oM$Txz6WBSKO`AQAlTavwG3mMMZH@= zl_@ABB;8cC=QMOGs`Qmmo1_L)(lKHPml6@dEFq~P1V_o(Q`H9#iL``ZZO}3QxK-)B z3C;|_bBBrUpPx&eJZXO6!jR1_q|09~q-JF73-y1rk3=BAp#V8T%YIq+ABRvift-0t ztE0MsO%E%EFAq7X!At+pj>_TooB;cjEA&U@SyR*K0e^TQD2OdwU2}EuQ}`8R@6vz@ z7**57mA65g!;2Wur>gINn+wED8AdlY>eMi1yR-rwNnyL8;1flAIm6#F=9g?jM^{%q z*uCnxl!U}gy4C7^I4XB=Tf~i2pH<7r*n`!ca{8pV4S5oj!m1DSm5?JbcA$RxgUI888=e{K^?Ld}% z(*dDp$SHuTA)wOQH0So-M&5qHSQW~u)^pzUjTYej8W-_as^62JyU(S zspbNfAw^XsB`xhBCnqwn^-spU`UQdot(@3?2>wW5zyz2FeqyS&bA)8-oFd@ zR472R%>_|8QcnqW04~T|UdF>;zaLW`k@YlQD4iOvSNnmcWyo;PG z)b4Ty_`kc~rH6SyAOpn-dLT@eAj0#$FvqO3DhN=N|KeATnY+6Q;)Fzwf-fsxJ<6^3 z{7t38Ss&RsC?N)-%10LQ9$>dAEKI<`;3vQwp9Y87d9{u)G_8G{Imonl$~j9 zZ9ReY1>gnj6CZjKatV+sfdu2^Jm3ycWfhoNtF|}O|K>Fr`)q}W8=GDh4u^Mmeiab7 z+YkRz<-7#Lm@&S3?b;5sl?&ds|s;j91QLY~906wim-+1j|Dt4dVs@~^4g(q%Qd3`J&g~~E-*4Q zG%voTjXZX})%Z$QM0(PE*&E0#YMoQZC{vLO1yWQ>H634CzS!U#Hu=J7zk>h~a_>ru ztVg(wGhJ_Cbeb|UwtQhJDJi<$yH!tUA6FBiHAY^@i2m@U z;1Chu_A;NqOM>gi5OnRDMIEyK{_=xkY)l)z5?fAN)EvRI= z${ti}LmTE0P&c4bfLN`=U{Da;tit|phzv5 zpR!PB&+$|LUmAeZh`j8w(iY0gHcl_~WvB6)8L^fFUv!F!i$NfAnFE;^+F69GW*~vX z7#kalkLNU1r*wzHkW(tV>qPS^0or6%ht$k^0QUClU>sQgEfh%8f0+q(CusJ4gW)taG&XX|-#W%A zFC!z<_wIcOQZjAijY#(2l_JG@{}&qcm)>i`%QDPY7yvq|w7!0Q!fV$Wg#o=mGTHqZ zn}t&sW>zQYK?MZo+(3vDzb=5nHe$Vkyh4=^+|Mc|M7aPuUCHt3J%x&n;%E1)=e}=W z78|8xjAuPr4<0L!D@TCqZ9#rM%jAPl_i7-z&dCCJPoVqOPk{wB0sgTb8qyKLS`d67 zDmy;|bAa=PO9xE)14YY@^mc_bGzJH$W|%Yg+s3`>yuV(s7B5E7G>?QCl^ z0?|syPDYTD#y);*l7!nJH}9DLC%O68QeskX00cg$LR!27rF1YEk&eGkpyr=Yk_)K7 zB5MHcuUoRYE&);$kml77naHCGlma$(U-oHP1roQ!4r;Nm_I}CTTsDliBU-p*V1?7il?$eKgD|#SG8pr_G#{IJeFHm9tAO(RGfULH5 zb|D<{Qfu!-!GMa*AvLnrD-XKCoCiuq#b!pumH;b)(DQNNde7lEQBT|IP(dHU%|mif zaCHpf=FQCe0cL@m?Zc2ujt_^-Bc#Qd5gP}D zgxC4U(3_y(e7a8HX#!9INPZts4i3@#Fbd?}5Y0W*{M*kpx?!3EBB2EBky$_BNQX%v zypDbHYU@vLyL0CbloZNzba%(p5AjlZS3Izta#{$M z&3m4Kf<0vcBr7BQLH@Y+dM$|CEe6mP5PEK+XPh}RHEaCD4Iea*Z)CQJ?~x8*Lf43G zpOJx^0Dzf|(MhhatApzWL@Y~8N=TsI2e~d6=)J?b4Q0e z%m)CMYb)Q;FO|p(1ODGauq!q$&PSFfeMrThNPJb^Lp605sL`yJEp#*4f3`@v3bLMk zj0hDF_}~cHds1f+ktN`zEKQo!& ztMo4Xce@vIfXa7|1G@nAu@^w(o`?ix?JE#1vpKZ2x0m0=iIPmHt}-%u!&Mdt>Nh=( zjWzekgT$QwPx9m%c@iQUp_Bj7slmOZL*cdG;d++jeIQXk2hZYk3j=jptv{~?kE+bkwkEY4oNNIfw--_5 zS!aoU_UdcOC=y>;AdDXpnhd6;fG5#gB0z299Mn_*Liof5WL0x=)CtyWCU6S1Qz~aK z05AvX6eGG+hq}%YZ*T(Z6+{2=6)lvt6+*S~KR5A_Ym~y(d3;~qBc;E^J&~OU12^hY z0k(r!|1&=;IzydufE`7CR-1xs6i&fXrvULGl@NA4I;0z*jFdJ|9|O{Zx`0pWA2E3x z2)stk3xQ^#jP3CHq?p;D`rz84RD)!rGLaW6p~&d2Gok!k@fQ%0*b%)AsKh(|@ZS&O z5epQghYJ8FZM={&laOku2i(ViYWv5JSN|G!kGMS4Hh@$L@|YAvy0$ULIiKsa$cUo$ znHwn$O4*D&q@G#|P&!FrIuK&;`-Q4HsJJlBwiK>Nu^PxbPYtAQN+4;dN;D%HiM`$g zS1I&Y2J98Gn!05XxQ^sf;jSYRFl$#L{M$-#$ikTROAohYOIWtGC-u(ch|ZBnd< zLiYxD#~||(_Z(bjXlUsEPPm-`MS*!0rKQ)k0d+yRdSu9ZxQROsf1>9+={`4MMXi)< z0~Hk2i?M`outRZ4>+gsxi#|PAdiSoom?;5b?b(b2^ykzX0a)b$^jjng#L5SFpv+Dr z_&XK-m8J+4Hk1u)+W0#F)>+|h^fOca9IKKlB*GL8+FEM)>U{TQF}wnc%4~uVv479M zC1}4~xkH^S=P{Na&4xxsOd!TUFosLmcu^$X$=>fKGfNO={o*An3ent#7|mK&@wW3X zVzlN4Rbg&I)>dR$nqXO^x{{Amp**)aJ*a#&@hA+hw~E5`m1C7!Oa84!Q3!HZN@m0I^y8Z| z9wM+MPgkx&y%nV99us)X$1XEhuW$7A{Hk<0e$pgg*8O=?K=DDnIZ>{;f3cP4r?P+}s($%DULoXb4&Wdys-0y> z7G=zH`P(8jN6E|22biClq&Sj&tw45YJ%-$jQ3bLq(nL3_gGlrxf1_ zgN>fE|9--;;0F(?tgqhXc^1P+#i@S-=BPa+C*Leu^pF5-Dmf zi!nra_D|9RqEmf8&|*FVSqwy=LgzloDC} z`$NDDuy8k*I-rl*T(^s;Vj0ZQ=8lg2@|SPiI8K(5mIj(cuZ8xh2o;vJbio&+Md#H3 z$ixSiL!mPS@+qTR&a+b0b)v#c%gZ*-paPI{s_BC}y8tI@o!#VEv80M9!TVmdwza*~ zhg2vPw+aYA^#oW~g3j~_Z<^bj0A6BtpdhOTHjJM0STKkRWYh>(8PQ?Mqveta%h7@8 z{$|7>e94Z6@cd@&+Ur%Ic@f!MOOzhB{v1ViU&;&DZh)R&P*gM_E>4)PdIHq3AULfo zt?b#CHClg!G1ZfzSS*`22kdel;m-aVHyT}An&^3-(GRJhGi4w|9s^;>K#A#m7lrY_hcs; zzOJwwez@iK4OZeij*?T|+%(zG-t`#NByxP;HSa_N-%}o7ygl&e4Rzd|k9lWkEYJ8B zCkLy@Z%5PIExsYzoUEg%Sq~-T$R|oh$RmMEse2`WT2$~__>{izyGVr06$rXxu}Nde zH0!N%>b-X6+i?_!R4ngEG@afY>%#D|LU51UDc9`uWM(1UslP0Cec*C+-k< zPQt&)2dgHVU@Ay2ep~)ic=HW&1|oFAyMkpC4D#nht$+JNP!Ny0O1u1LDI0VWt*h}$ zw1XR&$X~u+{47BG@D+N?kNS{Z&~qA}kOB*sMP$z4YA@sy_&wag1XI0<<`mq&dHcrN z#CvaBTYk8Ygrll`e>~~wV98lKINflB_4M^$S2hYwm$Q!oNNUqqU0pr<7`!Y1VPK_) z&CkL(gMudOM*6oxVC%N6}J&(~9&9K>ra+_=efp z*|kD~E|=fvS02PP`hq0pgql;wtA4vi78)9pwtnR9Nsryd6th*BcQ|AUf`3-H1L|GrC7>@+tY-O+0sRXH-;3E!y)^%}hKC@bTJ~+4tQdo| zM7hIMY9|1i5I*dcfctbHpox)ow$&;1S@i^Ge(l=mOYN92gW%aGm$PR|#Gsct)sO!dHPZ@*T zL;1@0o_z_)lXU5uhsT81ZXmZY#!7j`AjwQPfO)wii1>K7fWUqrBZDOTX0v$!<6#UZ z1n8f~fsCtiVZjm>`VfAX5#Xl*?B49}As`VmH!zsl(q9Iunf)_Rr$1=ByRrdh#OtMP zpla{|%M$lcd~96YgP5E&*(j)#J0XfUNHtXCi;IWiw@?MU+Sre}Imww9^8{@JiK0jF z1G{;vLGif*F4^k0d`u>jO?+S@cz%R{Qld|@Q3)SD-uy8}V6!xgF>G-pAV}vW+$|_F z9q+lja`!In2L=)Fzo50f(tF0UwsR6EpqZYT3B*&}wHx zOP7Iys2T*w%=?fF;nXalGtvd*b(9TW`T<%_}hz+M&-6tr$!IA|v`+Jpna<{(_vJMR}Po;>WzL4w;n ze95|S=V<*2{EXLmpFlKrt!X@(+>{Dwv4@Z5l2WoQ_J)${P&j%BZu0womfX$)j4)P> zvkG^Nw{G8lJb6;3I@7z`GH3-9t%8i@nqoXqeAbD zjg5gDkoqQf0!N&W{`$+!z%Xt5ibolbHJ-e9vf^nH=Xc|9F93 ziw-H=QYcbXQgo$gW6SS1Z*u0i9kDw4^9XRcQauAhLS?sBpIM(%pI={;-n4@MzrJR# z@txy&B+J*|e?PGFeX6_4;+6%MrIlsY&IpiKesF`b6|j~Amdv1X8t8anZ3!)^fdZhy z99Wlu1(5v?RR`AyDfA&4A?naIf|PE!au{f*Mie*@feJo^|IoLI75x?%dS@Nz@IFsh KKbLh*2~7Y82IPGJ literal 20635 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 start +Entry state S0 +Entry state S1 +Entry state S11 +Init foo to 0 +State machine started + +sm>sm event A +Event A send + +sm>sm event C +Exit state S11 +Exit state S1 +Entry state S2 +Entry state S21 +Entry state S211 +Event C send + +sm>sm event H +Switch foo to 1 +Event H send + +sm>sm event C +Exit state S211 +Exit state S21 +Exit state S2 +Entry state S1 +Entry state S11 +Event C send + +sm>sm event A +Exit state S11 +Exit state S1 +Entry state S1 +Entry state S11 +Event A send +---- + +What happens in above sample: + +* State machine is started which takes it to its initial state _S11_ + via superstates _S1_ and _S0_. Also extended state variable `foo` is + init to `0`. +* We try to execute self transition in state _S1_ with event _A_ but + nothing happens because transition is guarded by variable `foo` to + be `1`. +* We send event _C_ which takes us to other state machine where + initial state _S211_ and its superstates are entered. In there we + can use event _H_ which does a simple internal transition to flip + variable `foo`. Then we simply go back using event _C_. +* Event _A_ is sent again and now _S1_ does a self transition because + guard evaluates true. +* It's also worth to pay attention to how event _H_ is handled in + different states _S0_, _S1_ and _S2_. This is a good example of how + hierarchical states and their event handling works. If state _S2_ is + unable to handle event _H_ due to guard condition, its parent is + checked next. This guarantees that while on state _S2_, `foo` flag + is always flipped around. However in state _S1_ event _H_ always + match to its dummy transtion without guard or action, not never + happens. + == CD Player CD Player is a sample which resembles better use case of most of use have used in a real world. CD Player itself is a really simple entity where @@ -271,3 +337,30 @@ event sent to a state machine. include::samples/demo/cdplayer/Application.java[tags=snippetL] ---- +One other important aspect of a state machines is that they have their +own responsibilies mostly around handling states and all application +level logic should be kept outside. This means that application needs +to have a ways to interact with a state machine and below sample is +how cdplayer does it order to update lcd status. Also pay attention +that we annotated _CdPlayer_ with _@WithStateMachine_ which instructs +state machine to find methods from your pojo which are then called +with various transitions. + +[source,java,indent=0] +---- +include::samples/demo/cdplayer/CdPlayer.java[tags=snippetA] +---- + +In above example we use _@OnTransition_ annotation to hook a callback +when transition happens with a target state _BUSY_. + +[source,java,indent=0] +---- +include::samples/demo/cdplayer/CdPlayer.java[tags=snippetB] +---- + +_@OnTransition_ we used above can only be used with strings which are +matched from enums. _@StatesOnTransition_ is then something what user +can create into his own application to get a type safe annotation where +a real enums can be used. + diff --git a/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayer.java b/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayer.java index 6a2e97cd..01dd4191 100644 --- a/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayer.java +++ b/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayer.java @@ -63,6 +63,7 @@ public class CdPlayer { return cdStatus + " " + trackStatus; } +//tag::snippetA[] @OnTransition(target = "BUSY") public void busy(ExtendedState extendedState) { Object cd = extendedState.getVariables().get(Variables.CD); @@ -70,6 +71,7 @@ public class CdPlayer { cdStatus = ((Cd)cd).getName(); } } +//end::snippetA[] @StatesOnTransition(target = States.PLAYING) public void playing(ExtendedState extendedState) { @@ -88,6 +90,7 @@ public class CdPlayer { cdStatus = "Open"; } +//tag::snippetB[] @StatesOnTransition(target = States.CLOSED) public void closed(ExtendedState extendedState) { Object cd = extendedState.getVariables().get(Variables.CD); @@ -98,5 +101,6 @@ public class CdPlayer { } trackStatus = ""; } +//end::snippetB[] } diff --git a/spring-statemachine-samples/showcase/src/main/java/demo/showcase/Application.java b/spring-statemachine-samples/showcase/src/main/java/demo/showcase/Application.java index 3757eeb2..3e69b9cd 100644 --- a/spring-statemachine-samples/showcase/src/main/java/demo/showcase/Application.java +++ b/spring-statemachine-samples/showcase/src/main/java/demo/showcase/Application.java @@ -1,5 +1,9 @@ package demo.showcase; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.shell.Bootstrap; @@ -14,6 +18,8 @@ import org.springframework.statemachine.guard.Guard; @Configuration public class Application { + private final static Log log = LogFactory.getLog(Application.class); + @Configuration @EnableStateMachine static class StateMachineConfig @@ -51,7 +57,8 @@ public class Application { .withStates() .parent(States.S21) .initial(States.S211) - .state(States.S211); + .state(States.S211) + .state(States.S212); } //end::snippetAA[] @@ -62,7 +69,7 @@ public class Application { transitions .withExternal() .source(States.S1).target(States.S1).event(Events.A) - .action(fooAction()) + .guard(foo1Guard()) .and() .withExternal() .source(States.S1).target(States.S11).event(Events.B) @@ -111,7 +118,13 @@ public class Application { .source(States.S1).event(Events.H) .and() .withExternal() - .source(States.S11).target(States.S12).event(Events.I); + .source(States.S11).target(States.S12).event(Events.I) + .and() + .withExternal() + .source(States.S211).target(States.S212).event(Events.I) + .and() + .withExternal() + .source(States.S12).target(States.S212).event(Events.I); } //end::snippetAB[] @@ -137,7 +150,7 @@ public class Application { //tag::snippetB[] public static enum States { - S0, S1, S11, S12, S2, S21, S211 + S0, S1, S11, S12, S2, S21, S211, S212 } //end::snippetB[] @@ -152,13 +165,17 @@ public class Application { @Override public void execute(StateContext context) { - Object foo = context.getExtendedState().getVariables().get("foo"); + Map variables = context.getExtendedState().getVariables(); + Object foo = variables.get("foo"); if (foo instanceof Integer && ((Integer)foo) == 0) { - context.getExtendedState().getVariables().put("foo", 1); + log.info("Switch foo to 1"); + variables.put("foo", 1); } else if (foo instanceof Integer && ((Integer)foo) == 1) { - context.getExtendedState().getVariables().put("foo", 0); + log.info("Switch foo to 0"); + variables.put("foo", 0); } else { - context.getExtendedState().getVariables().put("foo", 0); + log.info("Init foo to 0"); + variables.put("foo", 0); } } } diff --git a/spring-statemachine-samples/showcase/src/main/resources/statechartmodel.txt b/spring-statemachine-samples/showcase/src/main/resources/statechartmodel.txt index 63067a88..fd9c48b7 100644 --- a/spring-statemachine-samples/showcase/src/main/resources/statechartmodel.txt +++ b/spring-statemachine-samples/showcase/src/main/resources/statechartmodel.txt @@ -1,39 +1,44 @@ -+---------------------------------------------------------------------------------------------+ -| S0 | -+---------------------------------------------------------------------------------------------+ -| entry/ | -| exit/ | -| H/[foo.equals(0)]; | -| | -| +-------------------------+ +--------------------------------------------+ | -| *-->| S1 | | S2 | | -| +-------------------------+ +--------------------------------------------+ | -| | entry/ | C | entry/ | | -| D | exit/ |----->| exit/ | | -|<----------| H/ | | H/[foo.equals(1)]; | | -| | | | | | -| | +---------------+ | C | +------------------------------+ | | -| | *-->| S11 | |<-----| *-->| S21 | | | -| | +---------------+ | | +------------------------------+ | | -| +--| | entry/ | | F | | entry/ | | | -| A| | | exit/ |<---------| | exit/ | | | -| +->| | | | | | +--------------+ | | | -| A[foo 1]; | B | | | | | *-->| s211 | | | | -| |---->| | | | F | +--------------+ | | | -| | | | |-------------------->| entry/ | | G | | -| | +--| | | | G | | exit/ |----------------->| -| | | | |------------------------>| | | | | -| | | +---------------+ | | | B | | | E | | -| | | | | |------>| |<-----------------| -| | | +---------------+ | | | | | | | | -| | I| | S12 | | | | D | | | | | -| | | +---------------+ | | |<------| | | | | -| | | | entry/ | | | | +--------------+ | | | -| | | | exit/ | | | | | | | -| | | | | | | | | | | -| | +->| | | | | | | | -| | +---------------+ | | +------------------------------+ | | -| | | | | | -| +-------------------------+ +--------------------------------------------+ | -| | -+---------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------+ +| S0 | ++----------------------------------------------------------------------------------------------+ +| entry/ | +| exit/ | +| H/[foo.equals(0)]; | +| | +| +-------------------------+ +--------------------------------------------+ | +| *-->| S1 | | S2 | | +| +-------------------------+ +--------------------------------------------+ | +| | entry/ | C | entry/ | | +| D | exit/ |----->| exit/ | | +|<-----------| H/ | | H/[foo.equals(1)]; | | +| | | | | | +| | +---------------+ | C | +------------------------------+ | | +| | *-->| S11 | |<-----| *-->| S21 | | | +| | +---------------+ | | +------------------------------+ | | +| | | entry/ | | F | | entry/ | | | +| | | exit/ |<---------| | exit/ | | | +| | | | | | | +--------------+ | | | +| | B | | | | | *-->| s211 | | | | +| |---->| | | | F | +--------------+ G | | | +| | | | |-------------------->| entry/ |----------------->| +| | +--| | | | G | | exit/ | | | | +| | | | |------------------------>| | | E | | +| | | +---------------+ | | | B | |<-----------------| +| | | | | |------>| | | | | +| | | +---------------+ | | | | | D | | | +| | I| | S12 | | | | +--| |------>| | | +| | | +---------------+ | | | | +--------------+ | | | +| | | | entry/ | | | | | | | | +| | | | exit/ | | | | I| +--------------+ | | | +| | | | | | | | | | s212 | | | | +| | +->| | | | | | +--------------+ | | | +| +--| | | | | | +->| entry/ | | | | +| | | | | | I | | | exit/ | | | | +| | | | |------------------------>| | | | | +| A| | | | | | | +--------------+ | | | +| | | | | | | | | | | +| | | +---------------+ | | +------------------------------+ | | +| +->| | | | | +| +-------------------------+ +--------------------------------------------+ | +| A[foo.equals(1)]; | ++----------------------------------------------------------------------------------------------+ diff --git a/spring-statemachine-samples/showcase/src/test/java/demo/showcase/ShowcaseTests.java b/spring-statemachine-samples/showcase/src/test/java/demo/showcase/ShowcaseTests.java index a6dd0941..494b7a59 100644 --- a/spring-statemachine-samples/showcase/src/test/java/demo/showcase/ShowcaseTests.java +++ b/spring-statemachine-samples/showcase/src/test/java/demo/showcase/ShowcaseTests.java @@ -49,6 +49,20 @@ public class ShowcaseTests { @Test public void testA() throws Exception { + listener.reset(1, 0, 0); + machine.sendEvent(Events.A); + listener.stateChangedLatch.await(1, TimeUnit.SECONDS); + assertThat(machine.getState().getIds(), contains(States.S0, States.S1, States.S11)); + } + + @Test + public void testCHCA() throws Exception { + listener.reset(3, 0, 0); + machine.sendEvent(Events.C); + machine.sendEvent(Events.H); + machine.sendEvent(Events.C); + listener.stateChangedLatch.await(1, TimeUnit.SECONDS); + listener.reset(1, 2, 2, 1); machine.sendEvent(Events.A); listener.stateChangedLatch.await(1, TimeUnit.SECONDS); @@ -137,6 +151,19 @@ public class ShowcaseTests { assertThat(listener.statesExited.get(0).getId(), is(States.S11)); } + @Test + public void testII() throws Exception { + machine.sendEvent(Events.I); + + listener.reset(1, 0, 0); + // TODO: should think if need to bypass + // S211 as initial state and go directly + // to S212. + machine.sendEvent(Events.I); + listener.stateChangedLatch.await(1, TimeUnit.SECONDS); + assertThat(machine.getState().getIds(), contains(States.S0, States.S2, States.S21, States.S212)); + } + @Test public void testH() throws Exception { listener.reset(0, 0, 0, 1); @@ -164,7 +191,7 @@ public class ShowcaseTests { machine.sendEvent(Events.H); listener.transitionLatch.await(1, TimeUnit.SECONDS); assertThat(listener.transitionCount, is(1)); - assertThat(listener.transitions.get(0).getSource().getId(), is(States.S2)); + assertThat(listener.transitions.get(0).getSource().getId(), is(States.S0)); } @Test