From 319dd2653a073f310db05b6121696ebfa7049968 Mon Sep 17 00:00:00 2001 From: Danil Kornishev Date: Fri, 24 Mar 2017 11:55:27 -0400 Subject: [PATCH] Spring State Machine (#1424) * Neo4j cleanup * Neo4j cleanup * Neo4j cleanup x2 * State Machine Init * cleanup * White background, Java Util Logging * Change to Logging * Static import of asserts. rename test methods --- pom.xml | 5 +- spring-state-machine/bpmn/forkjoin.bpmn | 116 ++++++++++++++++++ spring-state-machine/bpmn/img/forkjoin.png | Bin 0 -> 50788 bytes spring-state-machine/bpmn/img/simple.png | Bin 0 -> 22706 bytes spring-state-machine/bpmn/simple.bpmn | 76 ++++++++++++ spring-state-machine/pom.xml | 31 +++++ .../ApplicationReviewEvents.java | 5 + .../ApplicationReviewStates.java | 5 + .../ForkJoinStateMachineConfiguration.java | 74 +++++++++++ ...HierarchicalStateMachineConfiguration.java | 47 +++++++ .../JunctionStateMachineConfiguration.java | 60 +++++++++ .../SimpleEnumStateMachineConfiguration.java | 53 ++++++++ .../SimpleStateMachineConfiguration.java | 105 ++++++++++++++++ .../config/StateMachineListener.java | 16 +++ .../ForkJoinStateMachineTest.java | 45 +++++++ .../HierarchicalStateMachineTest.java | 37 ++++++ .../JunctionStateMachineTest.java | 24 ++++ .../statemachine/StateEnumMachineTest.java | 33 +++++ .../statemachine/StateMachineBuilderTest.java | 35 ++++++ .../spring/statemachine/StateMachineTest.java | 47 +++++++ 20 files changed, 813 insertions(+), 1 deletion(-) create mode 100644 spring-state-machine/bpmn/forkjoin.bpmn create mode 100644 spring-state-machine/bpmn/img/forkjoin.png create mode 100644 spring-state-machine/bpmn/img/simple.png create mode 100644 spring-state-machine/bpmn/simple.bpmn create mode 100644 spring-state-machine/pom.xml create mode 100644 spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewEvents.java create mode 100644 spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewStates.java create mode 100644 spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/ForkJoinStateMachineConfiguration.java create mode 100644 spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/HierarchicalStateMachineConfiguration.java create mode 100644 spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/JunctionStateMachineConfiguration.java create mode 100644 spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleEnumStateMachineConfiguration.java create mode 100644 spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleStateMachineConfiguration.java create mode 100644 spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/StateMachineListener.java create mode 100644 spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineTest.java create mode 100644 spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineTest.java create mode 100644 spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineTest.java create mode 100644 spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineTest.java create mode 100644 spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineBuilderTest.java create mode 100644 spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineTest.java diff --git a/pom.xml b/pom.xml index 15e0e3322e..7c1cacbd33 100644 --- a/pom.xml +++ b/pom.xml @@ -188,6 +188,7 @@ spring-sleuth spring-social-login spring-spel + spring-state-machine spring-thymeleaf spring-userservice spring-zuul @@ -210,7 +211,9 @@ rabbitmq vertx - + + + diff --git a/spring-state-machine/bpmn/forkjoin.bpmn b/spring-state-machine/bpmn/forkjoin.bpmn new file mode 100644 index 0000000000..0cb060f74b --- /dev/null +++ b/spring-state-machine/bpmn/forkjoin.bpmn @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-state-machine/bpmn/img/forkjoin.png b/spring-state-machine/bpmn/img/forkjoin.png new file mode 100644 index 0000000000000000000000000000000000000000..642ab6949d18b49012529d7c5b9b14f909c9d701 GIT binary patch literal 50788 zcmeFZbyQW`_Xi3{cZzgMm!yPnC~2g-l$KJuyAVI#_x{d8Hc_1T6?b9^E2nU9~9&z(2xm{p`f79q$I_ZprBxJp`c(`5aEF<7%bXW zP*A9N=AxnsQlg^d3br;T=9b1#P?8^F;}KM%dmeXfFw*<`KMwYe8BQi|kv<^VGN7V{ z7WqJdsj}Oh_4P>g@mV}>3A7qssxSE_wsrDR%*3NcHGa?+uyQm88s}2-m>ToF!t2+6*Q$%cl0y&ge zWrA{UF~zzOy|%P_7F7$yH54eXQsb)%)atj(M3-Ha1POVl>8PRQpA-lFyWiyv-;+Cu zrbWea;a3XaRlYxRa#6acGCdNLf6VCMn`;<}TZzFc5z(V{=q2BE&!U-_^;6LPb#5Ng zBg#(0z+<)KXFMAH3jDUd>BNuGHIa_QNhN-;u3wvHc_%!(hjt9(N#Xbc1qDYO_lnKv zc|4tH4Au(o_erKq>c>~vubbz-Y(A5JJQzyc7ry@9&OQ4(Zz$0d_BcB{Ar8xwA|+=} zpNM5?(eU+r@h&NctUZ_JDYkCg2!1>EEZ?phvWsa7(A;Msb( z>U)k`s@&sGB)vT$gyAh|DEJBXq~)|*#Tkf&o|YOBL|Dudfh**&&X35xz*1^Nx9dcp zJCi(;dvusy-HB1|jhO?(!bVp0N#dK7*2N(K+);aaL_N7F<)F-HFPzKpo$*%&k0d`_ zDT_2}%0~izDFH<**7Yc)FzKY_S}S4oW6s3Np3Ul6tRq2BKqpj5vYQ5?6N%->&<6*# zHj)0O{w!Z{zA}sOER!Mzmgqb;sSvsQ*8QekSt_pL-p(2BD_IPOFx_V0dr!k`nZS|T z6~TH66{{e(g9KLE18S(#UV|Quj^~Pf{{Cz)*DT66b z9;J&&+qpkDT(h|?nF{>|?QR4|JAkB}#lW;&W(uhoiLGKxgToPzpML#A?4e2}_IJ0C z7_&Za7v~khxYM}Xxb*u;ehXP2g`-ws7AMbAXHn-NJSNN|r7_#Yw8M~oWB8-#$I1zl zacbyL!EFblLtWZ|t4*P7EM8T{buddRsG)_6mP{|8!h{}q3*HRmox@v~okFGT8in|~ zC=s!EVnV@nccf;*S9_DP1sYbupM8OIhSJA`{VL2U301XRobSU_;7Y0i8|O!<05j<~ zkO8v`)g;XP917i!<{eB5^hP`0Fp{+o!aJ)IpLhdIR6i_OVM#=^OscoR+;6-SC?9AezLB@~LNmc>!etqC!`3HH`TU_}9~&C*CGf5X zyBIEOP{#QpRXo*rrWUAbh^B$!4(2JhwuHJ4#(B>-_-$bM3iXTOJMOel)^_j`o-^}8 zaNP>eA*nm&y>tc^C!z_gsR%hmT7-0h1RZ4z)){sf)?hoygv1jX><_3}SR>H;1F&!S z-c!6sd(Z!qydri=eD^7Oq$D+06hTicuKb%wTPg9JlAPO|v7DV8!BK=tCe36^xic!- zsLNFtTLKrdOWaGoOI{bTm%`sc-!*A;0;#G%CaL|TiH{R4*ge>(aK%4jb;e@LN#!%; z$0!rhZO~!R+ZY=gI~b=L<@X&K#rMSZkw&%9%~D-Qeiq}(byYT15+AP_Cw$9zN_xs1 z`jR8ZWfd(NRj{fPYt{wVFJYVCNfZ#BGI zKblM-LXl17P|bjzNwGlXdFeZe*OHN?X1PyF6LRZczEA)0v=d*N`l;ws{ik6{nWNUZ zRnjf?pGqap^QyKOH{CWjHa&X9jH%W@YxZl{Yma(Kdi@xr8EP3S7>-pLROLV0bFc+c zP(?)cXmmaAuOGPJl(LK3px)1!h$f`bO+V3dsQetnpkAYKnz7A1@#?KCmwpXu4cc3| zx8dXO9h6VEwvWe)#)k?qWYyAk*%MzhI3F$doO3ClDThji1`sxJmA*wae`|hafy`O= zHf@4<_>Gy1S+0fEC|~YGnH<=0Y~9>uRIub0K{;Tnr{5@!V>Z!`kB|?Vk1|!4kA#n^ z@nz$)Mz}@<2eK{26XH{)6Yi~=EwpWmouF;j(K2wG4Y}cxS%gV>=aO%`nX?c*c<34rCif8t=ivnnxhFB0tMf z0#*gbt~K`6%!Y2ot=5i}%<6WfuIcUFeG?t>Td4rAG~|CUZQSr2QrC;q6Dc#)J7`I5 z!FQ{>G7!8I>=Yzvm2Q33iq{%`Yk#YByL}6PyLW?sRR@m=SRsM<1?mg&0|yDq!K}XyR#nNBRdVdFlwx*A5mvd zJxl_sK5L5h`1H(1AxtmqGVjI{V+_*B3xQ*`dp**ABq=2wQBH6<7{2vNa?{eBff`Cy zZ+A;2jcBF1^?2$0QtrE%iOzaEldYQ40&QjtX*PV$ksat`Puc~3wqs6z~!N+u{x(6#NYRcxKp^j zo~29`@54W3I@4*kK&qs6k(yO%$qkUXj=N+n(v{attGGFb>GK`+bz=OXR*n1iF$?4F zZO?uF6=ehE>ygx07DlJyuj)V59Exi-TO3ZoZ{&ZjVfRH9t|W6iK|Vtt%45Z`Or=V+N}iDk9L0(ho{ z&utF3lS6pscy$ad3>em9Q?;(M*Lx{@;39#~gpOwWbkjf0X>B&{^`J$AN7Topa;?-H;1F)oPBtl4a) z93tMAuVOx@<~!*slWJQKBzCXg3tou~%!Ze!BgrOXv=$@8=S1hu<#OPm<#Zy!;9Hpd zF>1TZ6SDYLelw*&pwQNKp1!y6t8#Y!@hglPWG#fjoU|>ged1C+l?f4*ZZl7PK^h)`>plyE(fQ#&DT^IaWAL^m^^b13wA5M zuWWlI-s~9Ed7Sr)GY#5!b~|$4K#rBD73*6fqo|#z+h<)WSFvNXFX~!8ts; zTk1eR%2)E>6E@8Kw^9D2oT*0&E6|{Rb|{f0f?Q;^N8KtHjDnsLZcyXjO|rsbQ*ena z%vl(kJ23@6g|$w=dXK|=!C&6o>^>VAVRg%xa)YWikvZ`AA>wa(llu70_O2V8C(}KA zp|mBFjrYD0P$wY0lhm|>f_nTE@()@{iTV%<3OdbPMZ;c0PL|Km#){>&k zz|&Ar0?vHES1V)t*W}JtmezKB&Mzn*p5Oz%LoTyYl0Q6RZ}EasLr#HQ)W+7BoQs8% zg^f}WnVg(lz}CowPf6_M@8!T>FDT9I?cedSvN}0Au{d$C*w~t~KI7%(Wo2V$WoKsw zo?y0fv9^Eh%xrB(^=p$q`-mCa8QPk^vp2V~CWq|%`i+f){R>J;$cz5^?-!lM&gOr= z$=dGsv48`zLhi6WV_{?cYj0qw0OTs4g1NJ?rG}Wfm9e!Q@D9OeY@D0|4-5Wt>+e_o zW2xrfOS!n7|8wO(?)+XUzzR9RKThQq+L1ebQ8!S{WI^^%)r%+!lrWVC5tyyVDLo&edt}+8Wli?`Z(h0CneMypAIMXmCvK!f zJ5J$dl6ynJApY+M7GjP>Idd}QfA6Syd&7{y!eWA;p#S+1tl{k~^37=XzYAb-FHrw? zbKqT|Z!oa9lr)A2|J>tYOY)2_rvJM&7$2_>RC-*WJsH?Sg7+q9jkfI{L5s& zNdxYuIENPlVq$=EAryOZzw4ZMw$7>9X5#Vfy6O?kG9qWcIbA$zv)IcpVtU<1dn8l* zTH)WWhAIMZgw($b?l8*RgyK`HN40Dsr#Si=Nu_F0tg?*Oxg|3%i7jr>IAf!GgGoAJm7PKUh~! zs^sIDiE1TXUpA&Z-xb@k(FCS|+$VEtNXabdyX-9y!C-(i9C_dbMB=$5XbaC zo(@zES3TrE*yR`}x5NDb9tZyRAj2%(cZC8o@=LOpGqAe)vV&*QoeIbdu=a+&|B_^m zFW|aW>icx408uWz_mK(GXNabik8{kgjwV`csL)A7YU19lRBv)WvgKcF9p(9Eq@|VQ zkv`8oJ2;DBZL`5e1g^I8Bwu0$PQ5Zj%G$T6%QB<55<{W@Uiq3JdZe-ZbCQb+JtoDhfWR-oH%=ZC!5=Lw3e zn_be2Y;-g!;V%|2FUof5w_-=lkCtkPL_Hq#R)7K&=u2z;C>A19C1uc9x0l{=l@ZTC z+rGmM$_c0k&TpBUc~?1;UWQJsIb4xABW#N1=ZT3KWr^w`O?^@c%H*8y&weS1O)nt#m3)u2t55Usr3! z5RJ$^Ftv@(!zVRAU%m1;b0f`c5&N`LT zVv=b*j|rl)fa>J}u{~#eZ~YC#)@+b07xmb33|+MvlK90|KKITL7;z2`JZolN5+p*v zAdN}nFzpS-qH5NC{q{kU-k?vw`frFyV-G2YN-?O!gli9J#;NelhQnL6s$>3_Xtl@E zvF`V)dvmoTtp_7(i2VBN$H>n>)nf{-RqQ>s(UwI%&UXyFmDjG4NkWwM$7cu%Ii!;A37k7Dw@rgG3+$PDN>% z#V!<(GYA(}e@E{NI@-;16$w!+uT=E~- z+0^BBrtPK-(p@XRwS@XJ$TdqX#r1(B|4iFJH?Z9b!RaqdUqa+|h=VB0c&?2%(l@WW zJ+s%Aew&!eV>LQe*TyO=%xyVkw0IzR;LJaiQRp`ml>S=*y+QskMs#9`-`D?K_$x;v z7YT$(hxx@s6f;K=O%B{ikJiCSuiO4p$5y+R>Bbv| z*3P|yJH%_+diUd3XC7561gGsHhuI1l#pwfIA05I#Gz`jz8joC*Ldu3IKH#tS{mR}z z;>Z!13XzS(L=UQH=_A<&ceh?*vs)1_)G{~7sQ%e<R2?9*YPgI@@L87hIYC` zeV#{~ON$L|aBq-DU!7;g1k2)!Z#>in*LJhB=QqE6GlWS%6bTf0hadN!bR2{P@FB*# zgW-X^DMYc+ps&j}9kog_dKzywu4}K^vDrB|_O3snE(%#G=gC$aJmMgG%zSoQ7!kKl zboRO{jKs0&5d!+uWv$fgZu6ea%#4ecYx^PQ8HtdRBKaXl%tv?~j$bz14u}mg?<@N+ z4SP_tUmtXe-lzfCE*c*oOj+Xc+1sg|Ww5$j0P~3Co=Bgy^vO=O%z_cVUY)iolDVF4 z8-vx0)CL9@-40&xJ0&9R&u-{8IZm%NB-`!HrRK|{EYe{*QV9M10%RaK;VS)-0eKqC zetT;*Ujj6Z%q%s-&b-Ul5_J{%Ug1BF`@mw8XGDN_LOwq*E7($VuTQqSZ=j0Uv^{x+{pz&qkny@rP90;m{{6NP+E77AP^EDjz?rJZwCwfA`Lc>{Za z`fVtUkcq#9x@h0OfyGIj;7UKbM=|aAsNrw<2@nky5rl~^H~=?xy4P4 zX$h0rbN))lsmo>2R@nfSfu^bR#OXxGwE4L@-IZ*@*>f(UNl0A(t6YM`m&9mI$o-qd zKi@!R(CoM(v*qv)wipQWIzRThQ9dFm)SUp#a_EnUW{;r~q3CU^a1PloEoqkIvU?w1`3wv23N-yGu#ortB?Q1- ztYQN<8un?`{eV|d7eg(=(C(IG|M*R3L>6GXIh&yyl@FTrkEL|sPz1P8l551nk|4r);I>56K|K#NYsr=xrUz&+mxl!==K*w|Vota;=`% z77a^YtP$w>5<+%Vn^GM*&woaJsC+#g$X0h|HM#vwjs0S)9cxc{GSu#TeJo;)W7(#`RHWC|IBu=g)E%SBQ*_w)ma|yVDAhVym6g#1yeueL zQBHTjtD~FvJ05`)0VVn9dWa5TLEm+GqTwmBx7F847B=4<}PnF&HmU z41k7{$nb$1&~V;w*swHMUT{0W+q0vX`_U?l?sWZeL4IdNTFSw0HnuvHKMa38=xOuL zM{`}d*c3zAA)@vko!jbzi1S6S#r>@~@pn(SjdnAm>~hA4K7@=}W3VC2hC!k+J;L?I+SLgg8$Ja4~?u%A^Z?0)rQ>K^Kg7cXOq z>MUc9vl6n5?ww$e*`uk+J?2f#y;hy~+oh=V+VD)g?$()ATpm2-f0}O>X5UuXRK2rU zI(0U-pFrbQw;${2bW+u&cX$J%dATpW_09x=ckgWMqZQc}%z%l;*&zGn-O7P+*DL;2 zg?)-bH!8)M~yg-}_M^`v{rO{Jjs{ zbs!l%Yeu_&scw_>!9vU0j}X>4>-okHXZ)g&sx3;_`+oH4HOcxFU^zZ?D4S$GV12Ka zy_9F;nU9i1{Ks6f<6D28mW8yQd6DfVohILZv07-|vC=&J3R9S(shLDNt73b;);lva zIb#ApU%IQd%a*Ke6(^-G8)aotJH5A4SIAld!Npou@-8?}|=sC)0(1RJA|gXMLJxe3JV(8Mz?CpuXQQu;VKpf#`~_)uv276^XTf!c*##)OEWMXYoA#q5$UIa? z-FBZ5JTG@nr?J+DWPKn?6t-Sb%EcGkVSu`SlLCdI}l$@qz;Dt!@sG`cia@>YhAo)D;J9qYDBWy>?5(rhA)jgGA*_;gL#+2~f)NRm*t zEKu^}H(w6T-$%w)sY_pv&Gu=o3?kPe^@qf2mST4HmJ*YMkiCa3I3?BSKsJI#s}N8 zThrM)OpyuQYx?1+F?tC{s~J_Js%Hc_s zo5EoWy=U<<{{s$f@8(Fh@!9UQ?RH`Q47!zWRbqE|FDW26?{grNa6U*=pn`aNOP}Uu zfn<~G-KwD(`5&AKm?2rv0a1LWOeN?n3b=24_gb~ zz1p!Hm-F>b7F9nut!jE7`Sy>FpPm$}41OlIe6JE`rBge?{eJjMFg#y%$2WziQ9GwX z-$(1>dQI=IWGlCgdWP`>rDKa3?uuMOK_Vz-$838AKZ~mdD-$*OcK1_w?I;Q1XfvS; z1c12R0u*LBZJj#g!1wGg`}0j}h52bwKs`KXLS1iR{~~mU$KZ4a91mo+4XTRC7Hq;H zj)Mizp=L3!(r;C?&aIjE;BmZWRkiU ztlW${i}7r4jJvMO*12GiSTp2W04*|3eqm>Bccj&GX0^f6C?d$pO zJrV6uPul$uWa$C~zJMA-7+SD;Ny3izKfTI<;M1kN-(ZszU zl`3?A>hfWq=z2!Z0%87TGG)s3QiJXGUVd+X1&49Z_|v0yDzad`GSbCZcq^jrb23jG zesxq-?s}^?y!V?Q!Y$b{C!|V@HbX@BB=KDDLKiJ@i4+hO6W^7Az0Tz~9I>s~f1ah< z^zl2j8gk(A-Q{K9(=@*%UxwrC=J&X==RKP;v^oyziKgv~pb*8rYpjQY9FF8yefSOQ z35SX7a-9y}dc&PhquB`M9AM@O3fg)9*Qtn5~nQ8zJs|MSl zeKM;c!B4Vj*;DW(O*G{hs&&vlziiAn9W90dt7JOj;3&{#E^rZ!M}&0gGYy1Um`Jz+ zp|Fy2)?yJ_t6KSM^DWIzroSOxX_Z?7*|OzMo7|IYkL&$9$0D4UDde$5Ni=xYUUg-I z^OfYsqov^eoiO7wFjNSjkvkH-Ii9zWIi%A!!IN;>ki$!nVV+Hs$;QZ{I6uC9Z}C@1W0$*V;|*FJ`GdrGo8 z-9OPQ&77?G7QC}_({U+&Hey@~Ypp$c{qBsn{Mvioa?jKPWvK8}U(l{Ww{*wBcH_f| z>%8Zk1Mj61txR~4o8&^fK%)Dpk!G8b$MVnlv!5wVjqDOYb{ntn>9V|uvCZ5X5_-jW-%%^{HRRkO$j9&yzc64E;V}`OCk5yB7(&C zuOpQ$n(poH9K+C_z)tF3t3Zmqk-SGUHolBjSGAEGU8(e{7Kx~EV~JT_=I-`}4a@UH ztEo*3k*aoTJwy7pmg*Me!hT4+sdgXtvWa5G8?x?y&evLNN?o5eG=y8;zi)Csy;84y zvyME%XU~@(eY4)W*zIK37R~drjUrv(_CxS9!ox0T?rzMj)4L4Ag?6$A39GMYz#^GFx zMaQhI$MvusVZ}3+aH@N7kY&Jl(UnT(fzx!h2YO=Mm&9S)zUQLnK4-y>oe3D`&bT7i}cj!wXfASHr8hE2++y+ zm`-OWPEm>xd0o`{v}wG{)E?l zNI+)-r%d1rtmF3r0;JhmE5@kEcU>e-V&m1BIW~Q%;sP707HTz#h(4lxfjH4+^ToBB zIZspe9Qe^xIL%B+CsCy9uN(HVxylwY8aHz~+t4R=lGjW|1<_9K?{b;IJ8fP&~tWTY~`9mzu@JfWkfqDVVkpM&HL>aeb7yXHk%ax?Z9^FR$$rV{E3 zse7=HfE+hCBowHkeSq;#?YhC*vI)>vIi7jkCY<%tqgOs=S@~4I~$) zP662L-(;-v1jzY?LHA$A5u9(~WoD;cGtG$fXD(frJnSh6C&?JD@@el6wBmCC0JNC;UV{)0{XWaD1Bn1PA|mQS z0mldh)AJOR{|P|OqW9i*r%BcF_ntmHD<%UVoMuwC#Q&h^fi@*c;0A8vvyj~a zE8N*{xaimB?;#*Va{0fJA!t}>05i(OC0BbuBUGB9Jm^%KpPAA%K}~ZQ*BQQgIK%2= z2z+$Fs{X4%@i*b10HCZZz*Iy3`1iG6@3Tc2Uj1tc^(QFvH6**D0=hp(HURLfCBI*i z{O3|E6o5H@rYpp>z2ynAnR|a`(Sy!pIk|WrLzaWskpMo)Iz?OjX_@}v1^G(|eDkMq z62tVR?#t8ba!8}+L3)Qt05+x9L^Y1^=gM!P`oLlW=YzJ!Ru%hI&I{s3-J;W;okqTh zo;nYo`Nf(PU^Sj;U*sP_{@FxQ3&1#~+$plOVEna&5|g|{0EUTM{LgIx zz&?EutYK9D(yiZGMm_=n+>+J&FFhchgc>(P`8#!Up_ILp(Gc~>z^c;2V_6J^uPO18xFhGc=|RJv;cm{<6up?uE92=rEKWfN3~_FQgO--Il4SZ< z8`Osyk|eJ3B=kXmxMrr|Tp4_GM=_4+miKk_LENn1_{Q9{FRXoDktE5Ek^oli?=7-D z?^Oyo7QhOP00I0FbcQb+yx#NSwAVdFGL}^cJpRe`1r#N1@GTe%(wFXA)MDYE+?V`pvGN968zdC2-*Ot;5)6Po zPtQ6P+yujs`6OlVp!zTdf6!|F_9i<9Jpd3@4fQz{cSvys6;*a4~j*;55woada^Z^`zl@V zXf20T96jXZ#_Cm}N{!Oo&PzBY84!o@<2#Q`rkl2asI)W|pyvRz_ID`}fozlID2?Yg zNuL2VDRkXvum(=|#Sn(ie|5Z2ITt7`kJe=LduMrCnfX0)UcrUW=jD`!c`lgfaAdP3 zuo-n@ngg+^!oqs7)uY0g>6dDg;{oO_+1WJ61u-R3yv@b7HusC=piuyC8Cl0*)jzDX zf8OS2PdFt-=y+9w)+AB%ss>xd;P~S}<^Ioa%4a{pJn*XinyLS1+d-ctOlPA{0be z&aXfcp3a+@L8}8ii!nev6p3TiXPNbyW+_@P#!g&mxl+ph_IOzSF;_%}sOVMrI;OMg z3)d6G8Cc49{0k4hggk-)(%@W^w@U?10P;mT*#WSje0l*K<#H_Y&<<84#a8ck~D5Ra{f#e8tz{<`V6oEddH3i9Y9>(W(*SH?^Fu%&oRrOdG_H-o3Nseb@_+ z3Ixi0qr(e{c-|m5Br^kHT1e^w5fX609d1*UqV+C?F{>0fok3-gA z>H|#tdAhOt&x?@VsB<8ROtY2BpP`Mv_WGaZ+Jhv1eE=m7ki@K7Wsm-QuW#yr*Koh( zg_!y;N*~At(lvU(6;ap_#XfYS|G8Hype#RjhNk}$c_aaPkz8gAIRCxZPXPS?f5|a0 z6(qZ7U*`UMui!G^h!uhZs3x7S8p{@>0gWy>Gl4MvoMwdA+kz0cky%Qo6j|?-svur6i=$=m^;%P%zS4|&w9ii zvU{y$1a6|_H%&7C$&&c|eOBs>qZwoN%dn`OvNkgY_u2rg0LExx(v(W*1H`$=2CHyk8SC57wrT1^VjHd-20!NG3WAZEc3}<&1%^ z3Hj=cR8DpeyIGq;PS1UU_tz~N{>;ek<&Nc7vD+WUpUdU^^k`kN*VyJSHQ{w{y3uY} zi_^~W=sM&6k^zl|3{yzCL?-+E`w18OeHj1hYOR%V?PaRjSccDDwwNFCOdZUh2=E{Y zB?AUyz6>bvhOcgbhT z`66*X_Z1W-v+rNyL)v1{N%*@Ho*DXE2E^R7NPP%FN2Td!qv9Vg(wjHBBW6hnE6`S7 zpLa~Iwi)k+$LUs){16V0|1ePU%for&9omD0l?$5Co~wNqI?P$!Ac=!-!#6(KUhBY+>xG5$p~f6G5b@$j@^k!B;6Zb<@tsH% z9!EzZQ)+MK=;vPDY=$p94yW>KAQzR&Xn*?8cm$$@eg%(P-R7?hpTaZ?-izrU%q#Q9 zKu+TEZ~XY2X^8Y~l5T?KhtGSRCUmGz*t|1Di1#1me=7Axp>f~Gmo3oGeyKs*Q>rG% z87-VFT%Q4xi2Qn_0_!jHfyBF|25;c~uIV${==+1Q+q5CoS7iiu6%OuI*doS^Mx0pY zFVv}vg1YZ+ulMRIjTop`51?bYVZ?orN49o2yy}kcCV8z~@E7cO@Mwh8JCh|cHAC3o z+2>>SET0F6!?+WXY{Cgu*A0A8o^x`NaJ4$_)dUQXJyBv879v)880Grq`h2iq1+Wx` zGw~5n1qRL%6>6ego_qBe(fETcoBU-$_C8mm>bDe;Z0slt1Gb9l>kCYd=$L%Xmx-S- z_{tA7MMOnkW}E3FA0)41SWEVxur@0IZCv6|Q9IPXJu6T)dVABtAZH&CK9v!=ddV=s zkxkpYertlx!a?z_lmKr)_Lh-Hx++^}&f2vlpL|Iba9ni#vcQCdttm}CDjW}3HozRL zZ{vq2BR8DocD{d7xHN$Qd-{;|{Z5cXeCiQ!t8u;~g$o!K%^PJ&z6|+hwhkD^y8}ip zTyue+L65>NPbnq1hK#c))fZ0*6n|W3~@hKbb{K$*6;l(Pie72h5N> zJlg#)CJSy%%ODs{{HK85hX-3oNT+Rv)CcIpbs;q zU)vS8_=OLpRP2f zmyjQrur~Sxl!N22OP~MNZUI)zIvR{C=B<+RgnVn|?fa2Wn-Qwjg?_}`jP^&a^ac4A zM@#EU6GrrND^1>R`wd;_^joJgnVvn&OG&)-249K5I?4%&n4cSbSupBi>{09FIq=pO z+^g)_7aMmXqD)gA9+PkdLaC84L&o7N;6na>H)e1dXpS8>&FxbEsPAKm(kUIs9Pq>C zWIogj*Mius#bZ={oAH9kRQ1nB-_1CmMj?7e=9D(NPN^gV6e)|@?`q$JaR+M& zRh-whi;NH3?wK!Sj^CzPpKWztrYF844yT?vJ$~1GeP>i!wAu4q?AX z%dm(#9`k3*{mIFkcUvYZNLG%S17zJQ?>@F(0z(#iA;1{QOoqrvP4lmzr3c6Gg$U+- zk3zx=x7wS-OTNNUc`<%ARJBTmiSiJRQ4iI*7P~r+#c_Me{7z%kDV}FH6+pq|R%`#W z^UY_|ai*WUt{xM7#=+=`=Y#wQ-Ip8b`ajN!Wm%wa<6Q3VZbvgkgX(n>;Bf}oJZS3s zVbN$}CQU_(8MKhif&gi!G;d5Y#1e znn$%113%7qy0Z3O?(cM4iV`#4`|GDVk6ZNdCo0W_er}jftuv)s`H-X)fyo z=0F7Phe2UUI20F7N3u!a8z1PclzSrW`URtwWo{PNa`9c9xx#XriDZwV+@ZLH_{a#^ zT*QavH2%ceBwZo+E8u_ePDJrGMvFiS!s&cPq-~LmLoaKhx6o!8ro0DGJGmN(g7ip z=J2#}3#y{H9Tp!Gu`bQ}T5pX&{^|VwUee z!T@AM>lE{h9yBqIp*3;}%k#a6p-c7GNcj^!FUBN{Uh>)a1tueC(*XRQen6??AKvTeT_boxYwL}WsZ(SAH; z456Fy@q*=@1a2L#+JBfJ`6SFU3_7NJ%Yc^ey}HuqboKp@JT^zABpimNBwU7jj2Y@t zVdCkR*im}x_&Jdh3^uqNZERG)Tgm% zI*4!T1N=xvf-uo$!4D5#V^}t@k~;tql}0Q((a+0(T%*O0`FJtExQr+P!5l5nOd_<9 zJtv3TYb2Ay3FvoR%RON?l4R5SJzM{f#V*nNBybN;*cf2!3es&kh>sFoz#ylM(n%Og zUsLjwgh|G_64<_zN%N4L0k9}e0E{9wH3Exa57!<-M%zA-@N*m0aFu7sQQVmaDiRC2 z*F*Z%S;B#%AJJ$|cIowtH7K|_+IO|PP66U6x4sh|}W$moqpx?0RQ@H$DMoU*+K!V;{?6xXgRZ zRw75SU%wI-;S*rc4hw|WoUC?#ghjWq9J$_V`9~Pb@MI^jb?J^;-QK>XU_rdRge6IK z1ib1Y*a7L0e%M=^P;bk2A`*>K;D}6x~9Xo&gdO_Xi_ zA-Z5WpcU2^$ISTCxmZ>Z+CyO%T&6#Tzs~;nM3_TkBNV8W=xGd=*>R*TtT7#*GB|gP zZWjVStV-Ik1zO5^BJ8O2g`%RsoLYr#C!RVk02C%Dw3Bh8hyR7(U^+n9IOhjUgwbua zYlCAa5qzWHc@WhrKB;D|lrJ3$7!6yw61xC~vc+kwK4wIl@NMGmzn5+z)lFXyJ1g6%Du%dC;j7XKwqL^o>?7bUMvV}E96o#);ePOl-kz$|QSR)jhF*hHC-^o-U1|3#wsD z89X|l<1QTl+1HTRH{Qc{Hj<`b{KYt6$`a`tbH-9DFx?sO?fQA7PPiw3p>m7sX^sp& zhbPU`EjVCSO56|Ws>C5jod0kSBu-tfw09gugYrH73%HzO>x_#C#4Hj+$=JB$o@5^8iPGY5ED&up~)qQgnwi7G)mjVMdgZl!J73&$o4a1&$_pNDE57QJ6AWb z(183_X#@s{m0lY8!;7)o6Gb6sH5mhMIU~xAdax7OjX&D&Ov-VBxJ?I%`Nx-rXzX4` zY-t-ro5L@+p0b*gs=>V}SCn!%(XZ<;dXu7!DXS2_Q`$5LuY_IL6Jerc7T4R6*ANKL zkuR4_10*vw&;!6!=Lbj52B2m2q`(gOFN&dIvuH8LP~q?uy0w+B;D8v#gE7}}`k{Qm z-LP;CNN;M70Rc@laMKT00&{5m2$<5*fBs(p={z=RsZC@vbD%yc+Ek;BSVoI8?_f_V zK$HTUX2V}vop$z!+Q>4uH|nI8`#LN10ss1^4ALc&#$A&T}k&zJOCB)X8Tr+Vnsw{;93@cP1RzrR$pQS9Xl@V%#w zIiHDrn~>ecU`=wvI<Mm4oG#A~TWqGffhk?uUSq`}I%I*vFORtW$fqc{B5Dk~&}SF)z!ook z;jvG&ccVVS4+>tc;_xo};}{Lh)Ua;`;IF1)QRN6Dk#L=Hc4Xe&#VAYjSw=dfCm3|n z3f(CDKUAG%TvS`z#-&R_Qd&T|rMr=CMH&Q#p;J1C5>Zm=Zd5?J8%263=~5|4N$Gcu zp7VI#FMi-B%$~jXTI-Jgb=_75AB0-fOng%yu{5(@3XILy96X*h6A@Mek>ms`E{Kz0NUf^{oxqQv_&D zEzS_Wel}rN^mfsikpiB>KyB-#P2|j%h0IW&uQ(g)RtaZC5+53dNf&q$ep5va&qcQ; zoOfw`H|WINI!27@`+Y_vm@7;J8~Jg5ifql~g>Mi$jYeL(AY=OuE*)eM3w0M-ClTZ7ePo0U2HvrGy8HRHmaOd@Ut(d0m;Xy|C&bt7nFiJJy zk5-2FpC(31KOEvmh?$|iwX>HN2jBZb()a(KK(~-auzD{0>YVp%|xn}b7$rJ-=%d9frZI7`?zD&@mqZ}=e+u!^?TrAPIHSzWlyI7gP=66vv zr}ZBO2a_qIOpwRb={5Tokm*;x+Ouu%HT{vM$n#G=YU|iUuQuv9Cf@w|78?!ec+WS) z9Fg)8Gm}|obTAC3dr(a&$sE=!l~%g{JyCPEzJA^BH;#aV&WR|-zp5@b)3y1#}c)ZOXf1k zi$L^keZaBjSOkl?c3BCzxY$IN&ete;!fEgr&Qh@%0CYt_80_-6 z5i6CN3k?D`b!2`;#H1EC=hQrO(){%c?;o-5pX^x`nRi6%^XJcT(cBHw6jT{BqN<&$ zN-GnLdJq_wW_Fr2ey%$I(Yc954F+?3i#x8c1i0CP3^LWk{0zA@@sxSFuA>TMefhDH zhSQf|=hn4QC%@3cte3o=L62|wG8iUP(Wb(ad+U6VZ-f}v+zt|bQY`%+e5Ksq&xM}sz4;UV?38*@0yBp@@grzDp2l+ z7v{wSPR_E=^8%W}2cH>s4&Jcq&-#@3PQO{}T|uGuGd;p3BTt!K%#p$BHf})S(S#xe zu=tOP5BBDNlXkq$p_YoF6442qZZS}7`x((9?ol$q`nl;R@_Pu=ZU0pg7#5O{T)O1t zDtA!4*HVB!f5-p3>}bS&(+UFxTGd`I>eYP>qPskqsTdcYOVLjlCt0TjHmc@@##Wby zjYl0&Z?1`so`meFib`$~>Pqjqio>upRQX7`-)`H(2z*+u3)(xS{xO@Xxx*Ehs^z~X+6>y9<1>5N`BtVVNCH+L zkRJH{I)BL0^aWL^Mx-~ituXCicZocoYiGXEeVMD}VU8@?B_By3C~{Kh{hI0s8LRQ! z!Ir4F=@j5w8JjXoej{~dm5yZMv-&3C4M_nJNwsbj9`5Fz_ShDX5l+XDgAGXKup}Yp z$zQmPKq#aEjrizABrYY>H(FZmZ0<|rlWUp#TUb&UQ(^a9cI%^4BwV(QxCG!gQH{%Hd@!bZ5CoBbem?mQqtyeKc!OADlnJ-<1v*hg z${=c*2EUj>pZgH$rdK9g40um zk5*iMqup}4=(jV6@=dKBMJjApQzrXSi{$DJhui*08y&NzQ`T5H>tAQw8dpmYxhV`qe3Q(*YcAR0DG|>JXClc3SbO=w68Q;@aV?F zVX;C`lyIBA&#+DF1Vf+8^NFeyOFBt+`Bi1-=Hgt=&$qPkLjaAGdWTLg&1<<1ykGQa z{JJZR>si&*0)dthuc@F9Na}Xx$R>5|AYH4@ZORZ?y+?mAxL|#>nwxYSt_Eou?`0&) zTf#dvJ*YC5H`S(^7VH`kAJ5R zB}yU9du`48`|fLlcXo&yUB7+$SVhVomy?Qdjf4hdpz&~!Com_cNydNA>2e=Ey5_1^V<`kqa%lTyX9_X*xf!gHu zNtVZ$vK2G2u7yksV!0-ztA!7k2Gq_E(K_(RL`LxM++Z>FT;RC}A~J=LC)m)WAA5nP z&Gf|+c%E|BoWE=sYMd5k(a*io?zNLn;U}N;6_R5ka9v;ll7+>>qBfExv3hm7lnl=F z{#;G9!$?XsP|RW2cUi(RY_E|qsM;bjV}5zg=@3oI`C`H5s#l>R76u|0<09FGrf1e= zXZh=HM0&rhN3tGRvq5<*HYQ3@iCVn#ONkJ>zO)*uQ|s~LQoT|gxciw6Cln**dImF% ze8cR>`6;Ir^RIXNfX!*Szg!v&>jLM2T#;rr*Q2+3@t0^tq226i(w+RF`%gt$My;5P zjnz*$POX_Xcv3oHSiYRVQzX#h^-T1XY$gFb2Zje~CuxE0j_EJ?18C(z--c`4rptQP z200bWKj-&8s`Es;U8!jW{cz|BmO?ctsN&IcQPR2SUY&Z!V(r>z-wu(B!*CivP=fbN zk+X1ESbBg?i;cTwAGQ;H@5X5Sa)prZyt{X?UoXy<+-)PHKRkfRIPh#0=ni}(*0cPa zDo1HNM9`2b09Ccp$DCb5Ens&TnR~~I4GKZ-M6FoR{_%(2(i7%Z z$7{7k#wlXxNjWLYq2_KgH25y`$m+DY?V7Mg-_&u9;5~|BSvxu*{~Qb^ori_$IpJ+0 za~Nr!FF9@A)qbPSLpSR5;P^K}TjCOe&_jC)(`-h4)_DFKu}0i)JQkK0b(GDUMd{zu z?8_@{r_U(yRTm}bedNX%g92|)o=r>_C=(g9`BX!-ESme|_qjpuk7T^4&+c4p-)04&RR??EW9bW> zh97U=(T_nvBWg$k)LStP%J1}50<^A2?j8dT^Q-R}=hEdvv;g&Rl(qn!Hbk~M)AaP+ z_jHb`mkexuEADv8v#F4p@UNll@@{YG=V-1??;mDzhzK)k;-%e#k-N)QRaZL_tbh!i zi&qQSB2lQZXf`*}zgfXWb|rL?36E!Z*ne=mwQ5MD=RNDeljaymE0E%{I_FHJ_I$i` zrRMjQM$zR2uwHJN-BiiIT^tNey& zW;p$JhD8fTTzjdR!P;gQP|6wN1KGCz(+;{pib`_iEP{P}w)Z?T;ah5ESooQ)5%ZV3 z&8S4;u93e*Qo*2U&95qRp>tO%(7$wYqK!z901#;ql?9A|C=hW3hrCWo@ILP67)nLn2e>Rw~A&4B z;n);oQ=Zk_OsE%}vZDLm^vJWE{Lap7ZFMOGWUQ44PBsJTupH=W(@n_k^Fh(B8;9Z1Q!Ont_*`Infp}slz?rz`X zACg{QQT$Lj+Ec!w^a5-w;>6KPucShxz%Qj`tyq59+j_!cwl2=MDx$A@4KCQ=$^#&| zbO^Qp*W_ukI4mwwvk~{1{)XX~DJ=o+y-NytcpE{D&>|_P;d68X51O|@VIBFl-wo1* zp?aw>=_>37weUL(iqp=THCXUB`liY}bOz4CQ@>3m2n3L>jI=M7e8Gju(&%1jOgFeP z%wW-lKLG|Gro>7OVD0`09o%2(c1(|8nB$sRz z8#T_+xEb4!u_(1%9M0(|c+7(VQT-4|u~<}-I4U=%odWpR&yjZL8>_)#6DlpsZz1xy z3+rfSZt9B&Pl+@S-HH<<$#0PJd2TS|m&Dc4_{Vb{_xfllIky35I&;R1s)m7(vlRFWwD3Wj|f>wpEOc#Pq%1EJt5C?>Od zxyXcK&N_#p6V}9{0p|4=Dsm_`D$y^iKRE|b8D4Xe3x5qA(6}q?a*vufX|Q(|ut3W* zKtJRdX+l>#msjt{?HtFH_^BlP6bzGsV!eXUZA>^@)@w#M(%1jg`7?2-rW}o8p>HZt(v3 zbaXQWgXRM{j;L%ZgiDJ};~pyt_ODzdcnEy`zVwEhS&@mx4_{Vn}u736c5pe5kS3+|r5u0xp8LXAkc23Vlg)GzF5 z8DDSU6g<3%qq_6Aw2Oo)iv>WL5CyS(F;Gl)gg7pXE;7VHk<;h`0coOgy1TGiJ7pT} z!_&E>dNI?y--WZYmn>MFBaZ-lJtRaZ{u~a!_gzNp>BS#7iu42TjSUu?S4nLx)8@*7 zK1}im>JkDDI_%#GHjp{aZU-Nn#1p88f>N;=fbAJAKfR2y4`xW4`W|k1M{B>!BnJ<( z;JGxSe1gfE?SG*B!k9Pt51s~$M0Q>~bwn}uL-;f`RTI6Onv^x1<{m>ZP)R`cpyly! zk#5-)2{&x>v)}2wdu%c7G$<(8qu`+K<{gHpoJ$htb@yl!D5-^ja{C+MOAWC7>_Ay6 zn?!elRhVz^v@M@G4gU^2f~8x~jCm|_$)mRKjwg3z+GNlbrkix#($#eHsF_-rR^lA*~X-r3XMDQDd>1iw5xKr>K*N^rmGbZ6gnWUELK!e zXSRZBk%n%vN9>JNt%balZbNY1f>d(Xx!#T|-- z29F9-C53bw6fV5)ItDHwMA4uF)D_#DE?d1CJ{1<}CZBQtk?51ctsx8*~hc zFXIv-X2=EXUK_jhF;+eOh>Z{(P;Z@1TgKM5Zjg$2KNm`~6ZF{7B7b1@d_k%Q!tn=k zzn6<@%(HR`lOzI-sUfN^)|tt-QIH2vK1?z_IEa9`f$Shs=>ZW?Jf@`sgH! z5&4$0LVi$nM)8;A7_`3r3@%Q7?c*2B`?VeQOM&*iIBg)!Tpibxs->1$U0dr1l-s>l zztbeCo3jy_ikqGKr6g9}qUp+NO{psnU@~!G4I;8CAWP4gyWpO$wuuFXH6jNG1Kg_M zBr8;iCPkPt{0nOnV=?hNvaMJ#p+eYec&=z$Pn(x!)X=DP4iK&lo#A1qxns%d?3f%s6FAkuOs5Kz69;Kty8w3*S*$anf}p2L~((|;oWP+1eg@;*%msU=LEk@)1_MM6@xbB z8!9=>+U5m=%$54&Z^G_7T?wcv-Ykx{VW_aDMdxQSE;<&yg}k_bm!Qm%J@s%AQlvkq zH=?#e+$woxk{`wlaDH*-I@x=#!YsHY9dj$3&?Bxyg z?{n$W(_U=qYgG=bV3ItCJA``;5^HG5v=fhS-DZY9#Y;U150>o@LcOJg7SdF7WvzSo z@YM|n-eV3f>{CITE5Q9^#wHpa9eE%}CUiT`d5~7gsLlb)*l{VAR!VYX|8=L}_1w}m z6DXt8j!j8R>liefx`?nks5rIDo?wHJN#6g$;|I?uO6L< zt7X6I1I>1xt5Zx!FgBDH<$P7wb``U_(}9m#e>Q^Gw1Pnvx>Fli_$C~OEGf;_XqH#U zS^{XqfR&?-3Xb@%h{hQJ22T-=BBQarDY z1)o$-pmH{O?P+9VleqGUKzNaGpT43NtD8RPKub#n$(vp5liVt_uZ_lAg~vF|B{@^7 z;~1fjROoWFun7RoPJ*;UrL78qK;Wtxnws@PcRf}YTm3?vh<0Tq9s}!#N zDGjPqJGJFz?UEY;&U1C@Cp&XCQ?)>6upzj@HL*s7h({KT#oDk2lQ2((9sY6VY(YE9 z{g%-du(1^zmZ}pamnaon@~gB(X{|x!9RnxL zD7N}#;0x6kvLTQ6sa*jd@M|+gRMpu_tasj#3|CtI5~BUzlYmm!3P9m(xf zz7n8ndrtwi$z$_rgvHs-5Q_(GG=h z)|kl#omo?8b$PgVWKQ*}7ie*cU?#BPn$1wb(Lz+Reg6oU=XH_Xmw=xi$-e4Tg_>al z+!Z)vh*}k#B<5&ulPd1>XTi_A*}}3M&{_#=|=bBE4k+uAM*MKI)7J<*rYqqh`<)6t)BMz_MtNbwAp(kHhSI4 z5tK|aGFJ(F;AmAEtTmT$-J`f!`P!NlqCG)DQ7!KhjPp=PrUpe4e6tCr+#n6`m+;S}o9k1aI+Y=Hl>yYK=zhSq6gn@p9ej(G>c8`l zijK_0BYuOx3vt5ST&_#`N0TQvcPZ=2NTXn-vH83@OF}pbRdtL0cxL}$<>spWhB@f^ zFdMNqGc))qh}mQS?aId9)k|`|?;vrhH&A{>DHOA)Ec}nUPn!?~KrO&83lQ+}8Bc5b zx=fy)a~ie>G;dG0o7tszNSpBeh(|}~SGuEYo0Z8quAVKAGT6POGJYw;M*?Cx#`BL< zXdzYD8#X34itMFF0_-C^iIN$SY)+Z!k+WQe0}DRL>$x#OFAQ9ZQXyfp9UR%>K2_qE z``wosXuJnj(kqCpp)(8-Nyk7g$KScTyRX`hYjA!r1}?x409=vEV*$$ux;_he$G#oV zGHhf)))SJbBHex*TeCr+XBK!?xY4%cfA|V_&DLC#_EPQ*$krnaA6fa7?6B#VJIn=; z&ZPV!kwwKs$Q4i0Blkcf1ND8>kWoN~Xt&jH6M~SHAG7Jg8*luXNE^uFoDyWC?=(wX zHO8q{*S-8LCUI-1u}dOw$8OT<%PXONw42Lfjt84F=X+-`G#u|+*rgf%?0Hugxt*w2 z0qmu~JJxpf9SoO-EhWfk7Vl2^2)=N+nC1X%wKvkWMQl)z5sjE%RZaq7t-=$NWSH(< z)fZay*q+>0H0>uo)5e2cnWK!8QN;dULE^{3OWousinh%^pBSPDI@&70UtR?e~s;Fz8|l!CINcrO3fWMGDv2WCc`7pB}sH` zEh@2l+@CTW~T}QS#ZjSho^FpbeU2?fl)NwgNCQlG!AW}@28ag zXyLXBomL3@Q?Q^-Bw&-HK{L;F>D*t*TOe}murWm=fa$W}}*qAc|XZpyht?vB7^7k`dU3LsDhp_FSBHa5## zC7#Zsy+eQ!^CpGebXx#Ef2mXg}&A zoDviaS3ETzc!YS!gk?u_&n)8pCB1`v(*SFI- zSA<@E*^9J?(O`eSsrOk=Qk=Sc zhZUb{o=4<;tbxk1MXBiNq0@=Ye47n-;l3VOZ#?zO^xK`;YdrODUvJ4yt=JP;IzDU5 z@>}&EKJ?Fufjn%$UveMhZSqfU-sm{`dN*TtzPGVL7vKFNt}tO{j`jPUr#2Ee?n?bT zp4QSb)t|Q_1Bdu4tU;X$F#H&s&h%a9WPTh9L{NbA^6cpi4aLRBTP#%=*0MP_-$Y|G zb-q%}<7)g)nBGpeNWOcu*ZYsv0iq`aM;7IuYzHE1KMrV@A}$AUoqd%vPj2{T>b?xI z1ksUdpDwnd_O%zS(1IOC_EC#C+dn6Gat8Ijuzxoag zJH#W=(#Rr6>c~qW(iek$awtX#8M|{>bK=BY26buYmD*~5cu5XA(N~f8Y&~V-)dR;! zXm2J;=@A%Ndav}--gKp$DJb3skZX^Y-oHq_xeFzb@e|qLp1~EG?-0+sv*}9kZ_#X7 z5@{%WRjSoH$52#)lwNr;g-ne{q&~wO#$^7oP7O05OuOQ&MEQi;?n$V7MKM?NAo{J0 z)3z;F2#bQ}Yu!S7jd0hsrEXLbf5ybqXBL4{T><7_Bo_-Aa*V8EMj1yL(|kAFGpUNY zR{Xm%vOJn4?r6D8)Y`~4d+uz{Wp}+)b{`%+zTtEK6+_Oah={@cgrOQ?2-m?Z?6%&Y ze~kcu@ z%d1%uDCo3b(hY`5(@dL3k96RcwZ&Z*YmJy}s18{Lvrkf%VnO>su;61Uq++lBe8n`f zAv*?TJ8PJam!92AImm#82O9+z@;``G@>K93;Jx^ zfq=cmiSN7Ef`fEV%%vlx_=Q?2kV$Y2QN_3?JaO4tY_j%V&da~L9fVnsPBr)R>I%qd z6_svLA1vR{iNi0{*Mv<7O)`8@-&*E4;&$n!tjL~)&~KI{+`N41eHxNV_>kz6-rIsi zFDiDUA+rq8fczv7uF=d{m=+cnM?)4S?#BcSnI*KXf?7_sb33nrtKZRvh1nL*b71B< zJ4F!&w~P_n6PcE=<*^q&LkRtPZ(+-G-vB-=R|3bBTpzH1WhTLdf5WApwO9$1mv_vP5Z){ZH}p*gshdl8F*G2FKDGi?>jMA_&V{{t zrdA`EM);#`)Hu@eUwAY`kMJ(<(=hRy%R^pf;cv56^m29T#%1R_{-5LI6;y%EzwGfS(injB& zEf#rYO$bB~otP%zNPE!cO-^5rO>a{8%>9R==5`1z)hueoMo zap?hu;>&<*Rx~R1#YJvw&uJ=Gj2#0Qj`=w%2t$yfybDAb^%dEr;}={G!Ipd214 z4h{H{ZBye^#$xKSayI9#SFlZByg+;oOlr_EqV4I6ByRA~eWTb^o8o(#Il zW%Tt!`Q)zGTBn?Y&qV&UbSF?EMaq1(1!C>m#tIK%dyAW^V*o(P%jcht`WtAJqv77a zP5z(-*t{4_a@*WU%YmMlEqc&)>C5z6E+(epAs>CIeS-$=R; zhIq>;7IP1A4oLJsDfbOfHFE*Gc)_>_Kw{?FHiPFaC+Mqj@5>VY4sSu@CXD2&gL*Ua z(0od%=R|3XiYrH}`@U)+6%mWiHeUvJfyr)6&ezug*<`kKfv=TZ4Nitq5vlP~GEE9DP5V+EMJ^lKDsAaF*l z#+&@u`*ZivV{1^wO#L+Zqv?58=0~Jbazy$voQ>MS*qG5AWJVEG>_d>{)oEEk2#ox$5_=FJ~g_kwQx;LaP* zpmIKmmeP@e&^+gz_?*T%{`RE63ySxEq5*D6p40EqiOPB9AkV%;XpQrr&rY=(R0r3? z7twWks#v=bQsi>XWpn&0hthusW*uq6IfU<_?U~s_UoXIswRJee z+f=a51$p%TBZ#JBrJo%w)lE!jp)loQBZXgzb_VGj(DsV`n;3y-@sw~HB6(jEIB2hF zG=R>ZWmCkS@^#-DjM3=!BxUER?{!5*;~K?iD((5n4m+iqX1KjNa(5-<@dxzDw`a5z z`&X{3{e9VLV|x#oH1Qg4Y>4(7CT?FqpB@B06F;*W{dQ_&-M3w9Z$0y+%ngpJ277Zc zET%aYBQ}gq45R+mY!WGAd^{|62aSkdTf~Rh|G4F>=|ej$#p`i88PMFt$Id|t9}nGq zwvLBO6UKgSocjWuVlvWAEjYM~7svFkg$Qv-@bHhEr8GMpx(T7|_{CXe!D8JI`D~zrtD|md{#-kt>b4J_9IoAr_*etdGFiLi_x}#i#Vk4nTYjs z9(i@QQ?C(|*nX2Om#91rYd7xQ`Ki)}_fIF*u^)M?$*2S(MTmbtU8epwGz^x`Kx-S> zX$$H^BO^ZVPjk?SZb$04qbx`Ij8+p?W)$!)?Kuj-U&vX0Lh) z0&HE3_4(?pFK=wP+r_`mV~Gx~u)(nK%=+JdJH8kN(&{)!c6w{`&{rv|d+>`mGPa1! zkRQa*IaA$a&F+cFU|E@a$k=G=)BpDT0B`jW$p%~WCY9uAW4MOI=4+)yPSM`psxK?} zqU_;oHcx5;ns-X$8oiw5Wx`(+VSIcCT0F^ujuZoBhr=RE_xt>6Z8S?E5f;BNIFVbY z%)2H<2Sc*3d?HE@=uO*c(}V@|obv+Ej~J>^&&_uo#yRMlpql6=qHA1*gNDi8Wa~}C z0T~yf$1Xoe9LhSwBrMn_EAve=5mrl``k_<*9xAtxT}j~IpNlq!CUr6Kjav{^w4NBM z^^xKnYU!uvbRb$}q9*eZz*C$eQCG$$1oOyZF~|swNbfErK~C~nAEQpSPGQO0T&%ma zKgK?yGrmomx}L&2G7ZI=YPpdFfmA`_w`K3^zzqU&>Jx&um%ZD!PgcYyPPC?8_O@xA z;??dA@d)WBg33&!2-~qI7#DIpo5B1)tE(64(#_`fS~54hrj2f^vJ3hZ$4O^A+0T1I zL@#9y1?D~H9IL+EPi@)h#$U~(bgpSdr}tsWOwGNpE$%C!4UFq!s(_t%Vm{{A?0z$p zKJaRdO1!M$*xom;CvZrxNkQA4YoI~5$T6&I3^iY-$#FqN#c?R{d+o{y+ z=JJH*thDB92`}ocx3arYWUJ+wK2{kQif$&<@^AR!*nW*t5R};xmg*dUCc@{vKf};| z7fS#Y>>xPKU^iO2fo*g|dlbI2s+A%N)eHv#!2rS$cVNirLVBq%)0PZ$dW!CcR z)rBjFCI-N0HVDyMbh(S-nLE4bSLW-a$0wfy-QDbd%A&p*HLxT+JJm#er1qH(z@S~j z>i>%iCkWuI47EKBIm_t0H>`}#XUix)-;JB4wMq*u3S2M90w<9DJ~vxY?s_i`a3RBMmZURDB^28$S# zp@kzYr6JGt(*NCD~$)(g%My&;yr^p z9i(YtV+-#Xy5JlAy*mUf1;KpZb2IvA;~W(H*jj)N(o>~xlBoo~bUTQpJPW%S9Fg|D zuLf|KtgNgE)RgLId6LCPfZKf6m+y@3VR!*9ZD*%lhLNJsy)c(m{GeZ`o02DTz}BuO9Fws4EhIo>8msa5=7-f5=3{` z2wqY2eqzg!`ZlX;0jh*_+_{Z+exwvCe9p(-eV^7`nz+=o93N5--KU?;YbC5{TZs^b z?viD)9f0;h>r;KKPI|5?c<~!vk58(dO+;6k6XZb?R zWwmSQr*1Ru10qpnb1b(#deNB+KEh!?^mUB}o6>Eoar}KZ32woLN2Ta?C?R4FusK=X zfBA^Y;J|1x-y>*xiEH1Nvax|9z3H=yy*t^oeIc`ablq0-#Wu3{4XKDUL%`6EK89Fv z!jlBQ!8;Us(|1ok_fX{=|FBF_f?*+K!$(IRA^@2R#bZ_()NR-*MxMPNfz_a@AOrZe9BJ@4A%Y$)(e3|Q8>k=^7t4b6Yn|Cw8fO8+HagvjE-eO;p%ax< zmbvU}$Bq>Rh8($DVDgJ?dn3LV#!#tCq=Bj608;gR`VVoAyJBM;Ug?a8it(LtP=+2| zG70zsTCVAQths>R2phAY{om<+3z-)as@0jQbC8@Vwknu-ac?#QyFC?b4hwQ>>LlKXst+h-hAldh$kINT|QFU0NrhQIWhWH&j+** zrRh?Ql5PIpLZuP}+L4)Dq8%wUFX{SpIs<4WKlAjC^3mn0_YQSqil1-fYon1Ixm6G5 zVNnW*eD#CO*d%$Qk{yW>4dzMEmGecPXgsgchlxxunIn?><3e@unLGuYi!`Y&a3Wzk z_uTn=)?@Z?EN7Se{4&3SKYSan&7M;2*9HR&i`U-$sVg=>nK$6M+W5F|8l2ho+-QT{ z2hr$c9;6XaH%{nYXdi_9X%f!RL5Trr3S(NH2vL*g4x0v#3<{P>6SRya9{Y97k#x-8 zuLerP)2JEpuj&D9#j#MM%wMwa%tzY#HZ^IOHH~kj2)&F5mf`(CR1`7XmUIr$yO?(g1x|rt zYi~Dr!rwHi4w6MJ_srJXN8>$wtDPSqVF-$KJcvKPfr{BKzy5Lb|NnVZk|UI%D#y9+ zj}zHt+}R1#o~OPhGNFg($e3Kdl^3l=)IM^Xs)Lza�gf@SIUg-QO`umQ3S)QlWiV3@kS`RLu_ zHwe@b^en0N-B5{;t3HetA_L>(1cY5wi_f8aq}=_gUf2nG)Ajil!YWv&!c>Ai3HSjc ze0Koq*`x;-n{;zFBi_5Kqx+xKCyx}Uc>x~08vl?cKAOAj$y@yjnth5tAAy1lK0N^l zS^5yvlG)99GH4Ym;?c%HWP7J+bwV+y#XN~|orI%E2h#l+fz+WKn7T^l%EU}(_XpSz zYPp!D|DMM42kZ+Wz60-Zp-}pDZqGataE-y761NoUwMYyvh|E`fl>mNSL-FNZI?ExR z?2pl81Au`4dM-Wttr&d1piIHZx$BFQIAO3yD+Fc3a9Q1Atf@1B$>~Om@ZZwXt&j$6 zVV^sf2zvHw{~(yHlS6v|loJlgptIc%3U~Ct&-OLAn|*?b1xMhyYESBfy3P{GMDl=9 z6o+xYNHag?`W&u})j1j=W3}u8fBvcVcPefyQ2%=fNN8IlYh0$m zOfh{#OV*&#tq?J8imMF?T|KX)6~|*5h|fK+UZ(@fS3O;@HYBX3hMzm$y9%5#;xi8a zv7x;;10Fd{GI?*y%1A=s7C+U<}g>sxfEz~0g|jjz!JGlnRxYm?@I*caDnjvOHo3YxTXam5N%B2dax3{ zlCA^2(4WQ_7(>AcZx0GGXmH7$_dgt}vgk%X1Fd9haB~g-G1-sBoN-Ss;&%Lq7Z-c&QqFz_+@9OhbYM(uJSY_O0~Z?SL?Pe{J(Jbu ze|Dh6-R%l4TY4Tu4n40DaQ?oy1x+1;seGKB;2YDpi1yi+H-6eRtFnr6SZb4CD+l|7 z3UJjq%p9+=)xEgx2thfkJ46I*EO_9lf6N_}_#18O$aZY9Y5}!E@JM=65>uh-x?0T| z73F@%Ey`o#8=bd$tT*Z{h;Q{m9YmRx+U|%MV*l(~R%Fxl&e;JyU?K&E{{+~^Re-<8 zb{p8lF~lPf6OF+D5is_qu&@L%mHD5(Pn>zg&G56g=ql1KUKxj5DTF7_7kPcoMXF1>e;IrqNK9xi_*GkZRflB`^X_*37`Nv-Ck%G+9>m2)5#1dU{Uq-tfM|~2bX|c?<#kN zt@i@g0)fObenrg4`g2o}P(eoIL#QFL`r2PiAP#Z#k_)@!yafJhK*Q{G3UDRvptESi zdeA91ZuDQ@M-Ry(oo?}|zC4+8&hwG<4>cbSI9}(A|G0CkTJS1;PhGlms7!9*?*|w& zxEyV0vufvsm5l)TjTP_|I(Y`f$=DOxevFqOU#YSgp}8pALkQZyl(iAD_6{saH|QoK zJK{B&;0G>;U~Cia%L~#ING}7mY9fL|?V#~;aPzzBVqI|Q#ytQLVBfonHa3JCyjR2e zDUsH`KheRhf8T*y$RFvn@)dDyXKPBSQLe#D+z(#a0&u$2G0T3q&@a_d05J=hgV5X^ zY2XY8b_R<`;msxdQmxOZiP&X>e19_?VncJ_+jjse?|lg5(`~ii4Ka~xcvh>4e`%D2 zA{nPa!yMd1H!#|;zsh>xJ2=@M03_hzl^^KI?D+ot`cY=9CE&snI30o>lptm@7>XbT zh+g=&{Fz*dyEUeOdb5R(1OFCDzd=Bm9a2|=r7yN!0w`+FCkZF_Fg-J&*=C3N(ALKl zrjC1?6T0<7DZC735(%5QK^Kg=_6Hn)zqbNYPB$3>Z3m+y>-j{8XI?e%AafD?0$na^ zU_k8#>|Y16Z!T>{Pp$i3$G?BiaRzSAci^2|*NIL&{LP5}mMi$l0Fa(;Pm~mAdZyua zZ4%I3-7}lk0cV}qyizDyvWcfb$N;BtgO;iH3Yy5)`)c{vXZ?s;`Zgh;k{st$fEB&G z9|gb(luZNAtby}{bJWS17cir*DE48ifl5rsB5?2>QSzIdNZAKrUoi7kZ0LaC*4|J~J zfu{>z1K`1eug01;MGGK$5Eo3*RGcZn-nbl(|HjV5YXZ!L$$tw83}`4 zQ3#@Q&bi$Y1uu4)iCeyN^kQdB>YmU+Z&|c zv&T@HeG&(^AQP>T^^=E=pl}YmV5q13Fv>6wSyKUBp;7-kAu9YMv>TUJON!ETGe#-v z|H%swr-_XDc#--ES6eH}i?4OF-7=9{m&X-BwT;yLIbh4nR9^x65I4`Gcf&fl3W*AJ zfLAtu0}hUf;JKN*hTtTE(w_X@1sdd~6Qzf;rIwh4v6F=R7#|f<&=A0R8)iS&gJ9P4 zr}Udr#ITHIUnHAPk%NPS^cD8NXxl+r#wHfQ+c}IqY%LAiLtQB1Q-=mdBBTcZAuUg5 zaRo670kaaO%2=FhX6Tc z`!uG)fuGsju>z&+@0xvPAO>PKWme^bHI{bIjLRTk(wRp|L2+?&)vz8SOn0dc)`%?$ ziX2W8Pz5y6eV}iwpB(D%Pmlt{@4=6E6|<+gMXz42o$-t0qZ3~r6-&+70%@%l$aIjC z;X8&EKw0z|u{-&!gp>71;fH@kqT-Z40Nv>yvr-cFV}F* z-~wEV#@Yh>D#T&$wi-d&WYnH_sR*CErH6--Gp>f6@qY6l;3RRV0 zGZ@Q%h>!4`Hx4+S^z`imVvIh0vj9efI6jg#@JW{cL0=s0e12)R1`;rNI-NF$ec1!v zXSh#>!0tEz26z8odsiM0W!wEr5y=wbDZ4}wD#@0mBKuCVj3xWNlieuMqGZiB_Uuc@ zJ|v0k`_3SYZS4E{yY4~H^S?tAX*y3Td3bH3-C?|}%#!k~hb8_Zu3 ztg(*4&|$dY3CfU+0D;2k)(^(NQzCTO0J#n+?VE%LZ#iLQ0rHJAA_b4{_ByV90l?Uh zKo=31Y02C0^v=%>m(*d5=Qikqe#TPE{LH+pT%aVENt$cJt^6*uE>M(V|DEH^x(C;c zqXet#B4Tp_eM4mM-I#!lE3n3xN^tyNlC{xEXyO=2lQ_}sg6==2XMKqz+RA4fKlpJh zA~z93PQ9>u8i{zOAj{c|obmk?o(3;l5|@3`S(m-#x<*hBYvzCdu2~1OO_9IoW}7|< zAr)sRs3d>n=++2IQ@l5B5#5_E1x5?8qh{A2lsE};`3sP@9nEE6YgMejt|(sDKY%;m zHNPg0HBPQ8pO*V;?FYF+J-}MUbWBto$<*|0x$5aHM z1q~DZK1$-wB)y8*;YWUlDOoo*ihR$tL4p0c@`D$ehhqv4PQklKw}7=j38)E*=#$S7 zJ(5g*2#h3CVSf-(0C^uk$pyMQK`g86>N$l-hP#)O@ty>KX?w(YSu4y0>!+~9qx5tJ z_B$%{zVjSb{4`JybqWy|_3t;mCG!^V(pt?DuuHd`k)%ZP%=%Zyj2KDzFP$biubQUF zI871w+KYzhFRFEv6puv@1uPf|8dPjhPHjWB5(&O3&d(;I$c_>fgPCPVlGmSCwfn82 zG2}g;4$@)t#fDx9h%L!)!E{#;z=OQFhjzP1 zE;!VOjEOVhuA!G->GSr*Nyv4jiKK>3;~KXjtP}v@MHmsAm^W?|8&UVqS`oeex&|c;8Rd)c``AfMy(7#Fh{s`i*lj^W& zj%?TdfLvp}ymn*1r*W{K#~biA9^7}X_?qOgKCXVRv;4 z@6<={V$Wq>!nQ{zMk?r#)n+|Wm9wpu(UZ>R)S5+Yw|Lfwf2`c>NviYj1!q|C@Tqd) zLNs-`u-imD%zrn@GVI<)(0YMx(OgziX(^fXM2v>@{*zs%s0w0!lNFOY_+4fi5*fYO zoLW7WUsT@3I`wG$T6$W$azUWr#gu|+TRa?M0;siDu*SwZ6)SMo6tC;pEMQBjN3Y)U z_L9e`bu;N+?Qf7dJ9JHPu_-356?8c$%Y4R}+x&<`$k5{XpjC1I4L+C-ECX9WL;3t1Muhv>;Ll9MDI9###h^m#!C>q$0&?$vZGROCyU8oUV7-zssQC z?+8X&eP|W-VEDeucQXvP&>sg$;d^-2wB;pKOA46cELK^xf%#WWVoUSc!QM$ zuGo&i{AXiq;N<&vtuJ+Y< zB+gI=_qTNa0%sz!OH!YF4qJVl(Ww*oV0VII%0d7f@H)RBwrfKWOvsJ0Lfr->iNLI- zx3}EC20fu8j)q!Bze&SDoLTQR=?TX&!6@2Ef8-F&c^-LWy$*Wo8o!E$wMFl>nWpFQ zTlm1XWfi7c8C4^u;bSN;X$^$;T{$tfxQwXR;nkB`7LQ6Mu* z4o6~Xdm0l19|W}b2C7oIxw+YbrwPTD9n&HQ)B5!>)YRa9n1ykllV6iAMqmIz z&S>*pUg7)__vkO<<8pruZ{BL*p4O`%P_dRB)WMvv9; z6vht@&QH?3-gx%!?M?AVONV}$o6j0{hTUOzDGG=|?)}{o%2B5FXvQZ12WcLqj9@?XOL=OD#nEw zoJsvx_zNCc>TZgZ@3$>?KP%&8{R4faGl5cEHO(kAWE*SWj7Odt8X*6cy>4&kzyj;u zx-417G6}~n-Z(S(rhJe#Hc}aHikr`-R>a#^u<^TOD9t16%7y@S1bTwi`e}KFXVpQS zoij31$=celWGL|MF;oS5lR|aB+XJDjSWDvu>4KJCr+>opIQC8Fv01f>uyN~?DfMv& zNLNWJM;Za7=|u72LPXL1NcKvP+8hNTZ^eM5nnn8-mz-j^9ZB~N1Z-~JZ8c1&M)&2_ z6FGxZP=c-aJ+L(iDr&U8*rs!8%ngUa1#p}Rw+wJR=}Owd-MW0;%V7aDxdr|Vq-;h^ zS^-13nt)g^T(?x^G-e5F`e9unJde7rJPiM0PA2i z23B&ld|}#Fh%Du~_9zH+(0Suz`~zvu0>_|aPxxdhAOYyaF*7qOI*8`A*;sQBQ`xp1 zZuk)1^crp>P#%KJDtJFdr$lSuXDlId2jhdkBv8$X;T9hU+JOAYIcu!; zIub(Ae8=r1C>q27|11|hAegIB!193S`pBR;2;U1)yeWP>L@JU$4Dzs`BOIRS#w+I@UEcLe$gQ8=u} zE($c6L6*=^izp{uff-|V77$OH#!Uh=UM9+9{K3frfv%Yn!0%isyruxm1Syubbd?rM zJb>KV)rOcUyiSpcpp=5e(45b5u$LMg74~P^u0|&wiN|woA0OX3>Y!QB7=GovBW6HN zI)ak}=tXkgrj2-4TF$a*Ca5>n{H=F}A*d>Ys;qteY)j2NDPoLBsO1NAB>M7zSK57@ zO*@Uv-vX^&k#COlMoHFgB@3FGPn!mPcfaH=6z0Rm+uKv+Df+xhf)sdZYQ=QXI zd}FUn;?77z&{_|_6#v`tp9VR!SEH$H-p_Why6|b_>~1IK7X4opG(|{eJ_(gJVVmGUWx z-K+VL5-sz4IX5<&N+hI1Z+>*y7|W^&F1^XU=&4jy|D5~L8sckI*PF)dkt&R*#(uN; z%(4dwfA*Z2YwtWymimYV+D{n$7L7DTjqHsyCqBS}-`G7tD(^#ge(Yr*v=f=1ii%_b z7)l4>zQDgd`htW^oBAVQpt+Rx0*|t=?jaB%tM`7OJskxfOV=wg&ofA`1vjnig54O7 zXU_;K*RN}oB`5PJG!{3zcvtAAew7Rn$expod}B0j-)fav{CdNU&wfjCYwlNj#nkIf z2XS|#!KGg)x^^AbkvequTdHI27Q_m+(*5&Tp3emeQ{Z)6pcPPEsNA(K1>|Fv5V7L; zneK4Uj9e-{a{bAO8R|d zRxGk-<5`>jc>%*jO{BT~c4vf4zqHY64$n-rRN^Cc&gV-wH&hbd?QQ-1kiYkKvZK&K zh5rz~dWKFtNh#20u#sL@XR1O-;z{$M_8j|5 zol}QFaw@9f`!XSB&Ut@O>V?CV30mq#LQHesR!Hqiqf1ra2<<>-qTBv#N0F|U*+{l4 zTqdKtVsq-(9?8_8KzjA^*AK;Yh~eI|_DnZ-Dnbrz@`>JSuXsoF>0iExXwW~NC`B>I zbzpkR3AG3Op)v{(`G{16n>1w9sl%MYAYd*yHkP(kOU#2qt|e`qKrJSLG|GUnLxXXA zKhU1J*TO^JVD~Q>7Os!Eh+S!76MEuZtAir7LBp+UHItnZB4M?0oJDALsZ6FS&K zO77kk(lPf%qd2Y*ae9tmOqFHC?cR4Eb9J`{@ED2b`GXd9TI_a<770r{>&j?Xey-cp zQ+Xdg>^UsaDasyVAr#hTxLO_bAFCe4tg#Ayd@1StjSeyw%g} zis^j7IO>JwgH^fiN3Tp4=r%0Km8ZD9m<{&4HAtNO+~r$&zU}w#IB4&^wz@lG2L$X2XWbNw5WazM^}VL*tegJUK4Xn%sD2forxm!K!#?<~Xku43sJ?K6AkTRqiFJv(isCvr%lVTr39yTPgI~btqn)dt3vSRYq0%O+-ZzJ`Q>@3P%8ezfY!ELCoJC#PWeBgQ7H?+exXZ8U8yH`Ax6Mk?F4x@9!{^hb$98aRJ#GHYTa}9 z=0MGOjMmjfDY9Sd{3qE~&!_+-Kkpm^o%$5zKJwjZ1Q(tDs%{8lPXW!x>_MT$YrMav zTH|yrk(6r(kdOVNbrEIoU~b`+a+#%B=}c_&MAnE&|Lk7blKO676&?}sys%>Y8xe(_ zey{Qz!5p{c43BCE4P~14-w{o5^y}!@#f)^M$z0t%t+hxim+md^IU|^pJ5BL^=k$I_ z;qPR09%5s?#Yxa;#-#2u^4(NfJDvMNyu&J}kIo^c=1=Oqym3dcXTIKrA7hmu?tV>G zVC-pP9RLHS+~XFRt9U{0=JcC!McPr?Lt>nsv&vP-3M}g(up7kAi*4pciuHuLV~HM~ z!a=mK@y#W6!=_KSS3tcs@8Y*_46B;yWh7c1iDlhsK9oBwm6E@Y`B5>L zy=xcinLQ{k%v+{|7p0Zp5w@c5&O*cEdC*-`RalxHNc3cDp>u}rD{pO-h6S^O_~#hs zLOq3-dcCX2%0(UnGs4&>$}&ChEDxt%ZBl_3KYJ#%Ft#5W<4T8E%GQuBdA*v8kzB2z z^gs9X&hR2%ZRS@KqRQ|Dc}E7x?OLCUoasG+%j2&Dvy#G(trxO(-#isv{maw_7Y0#& z+EgsRf&o+MF@yv~Bxd>IQ9Qh6a>2!hHE)zAb^9zC>(|`=wALU`5l@sdYX&rT}S71eupbN)fQ~@k2(H#Z>VZSC*wO zZ0}p3WNO|Mr7Vl{OOauS$d>$x)u*4kNJxpW!+x$^F{s;arQ^|R@m})KqK<7BecPf+ ziYe~-=(S2eU!pf?<<~^N0~b_`{T`c&-bGN&K5ve=wX8sHbl|>fW%Jg}YVOyJI>OqW zSayF-HCnNKQ`60gHsiKw*-Z0Fm+H3JkV3xOPxEregOHh-XW@D&Vz0@Z*;@AnHyiWQ z8&_VXoE1c1PIUbq@M+$lVgw;uOq?YM1kcMTB--_STLdmzrK@FzLoPk4bRbrwz4|N) zZQ7OqkCoG_86wJeU7o6d4RDV|*m!-Ut(s`P6yzd`qccBT);sdm9GM~R(D!s4sNh%S+aZaq{(;!T}itI!zqntV1^CkD)V>4xes_A6%MoaX3#8U84pMI zBN*sO4xS2M-g}KnCvBYwK5f(R_}J|Xkd8N0m2kKPRslS5DGt5I5`2CzBE*r4EEM!3 zQv&BUdt_wfy-#hK>Rf^;$p{Pb4YPq$R2)3=>H74U_C%|2-eMi6mNbK6t53xbigHH~ z#l!vdwpOhHqy4_LRF>uGDjRUi{)$_yqjt)xAuGLg9@V*%qc+An^^)2S#3ZisZ@8ZH zB{@33yE7?!tGYDDAtxu+>U2+-#glLZ*Jfe$l~|lTI2R^`ft#)+3Lo|>ea5rkhD4t_B0QA?{udQGQW_> z|4=XCeIV(D+IJrj&UWvqzFEE{;(uncYWUDI@3-Ub;mAQ8&5+A2)V`zi2v9>);H5)Eqg?f6#})}CYe zvz7H>B&oak{D|x_!Dq_sX`!i7eG(|*nzC)HAl8J^PhA1|WirULU~FY?iKQ3W`eLf{ z@-r-Yp#R+aOsANvs4vptavH{~tkV=9T0#RfxthPU?H@WteBliY`&!W3utfN3FyYFj zj3;^Y`Az|1RV2Gou|51km&dnnMoH*lNGvdx6s$2GzFBbvI=~iDzuW)2_Rz%+u4Ojt z#3mIxtDNfGrGGwZHC}Vy9QS>o;|pS${=HS>NFMue%R{4b)lBtfw;76P0i&sfz;dgH zjSkj=b@CRa2i|j54}W%Y3dxzrDQQVZaB;j9(YZOOZbd~4N~do{#&C#;YnyC)TR4;03PQzb2jU06NeKO z5_@O2niaJ(3PhLL`V$;qu>-~uO>_4cS^-@7Jjfk zeY?;fupK!fY=)P@*W%hlOb`4jsF!gdlpZ=pRO4T6lN7zbmwe)sA)1X(UtPOf{5_Y*lo+(2^@zJZ2$`Msk?6^P@3^0w92pv4ZC_&Q5UdV0p4=+Lf`qbRV zCEz(d<|(W`9Go6!W``vd#wh`^&q4v3&b?xzEi#s_(SJdn_qtd0H9jX#t~Xm8$ytM z%CdNxNv`OV3l7&avT2^g2t)cN%4YSyyI2eXJgizS`vDBPf{GAS4+3J+<_$^w2+Q`` z4`Zbn-PU0tN!1RQQokRon4mRq#06Krb`^!@R2WBKXbf=J=0`64cBnN_ZyzJR;L0~u z&F(_5R4|jX5q}SR*#dx+M-fHwEa06_CNAh%#a#9eT!>T=Jog?AR`g09`q;o>?H5!} zM3Xe&X}sYN344a4nLK_BtXmw!E=q#yMS+!IGEPxqzn8qHFX1zaE=H2_%|q}UsiYae zl9C-)SC{^I9dz*z769Yj<88ry4cY?OyMQ63;QqA|)Y05p1KF1g7vr@`-3NT5{$NNS z@qr^kcJ2Ki)a>}WQ*aO9=hfF$Q$u%xi{S@_-o7|H#I1bVtyPSz7RuQ>g_91U#;O)} zh(ATb$G;5cgKkS4pp6}M{1T1_q4x7fIoMG`FBGW|dZH5T{s;3s9#0T61XBgSnz#); z2Nz+`qw2=&h&`v&P1%*=+X`4*kQ9P+pE>-#c{0Y6(JDhp6VkjQB!44(N53d)iF3g< zpgFJrJGk+iqQxtGFYNhGu8$9Zs%CzC)Bc-M=IEAiLyCW-2R)Ys;TbxMJc>+Cq=|A? zwW~IEYM_frZ(ln1-#E9A&sDITC%fb!?iM9q!rssyN}d2sfPpB5*x~$-9JD=x$6?nG z{t}FzaZFAW_aT0pJIh((a_sYiVbYzyF}!#G{(oQkg@9D?&oHsyJ$eCR^XmSI*Z>%J z`pLqv^n$ejP%bp-0b;KW{&C6CLNY)o*NWXy!#swIAXQiPrNHJpRi6>=kJ5J7Btp>) z0`3P&ia0LF|7-ul5Fzp7E|J9qig~pUrrZZH}Vn z_h3djk1&j~z{xbOSvmoWZSJ$V64lXKfn7m@-4)O+mDS@P2VU72E6(lX1VS?$ccxfm zyQN#u3Xm*hO>blFi z&({!2Jxw`!08Pz#LMW)zF_+pn!r@-K-4_0x=6)F=ZV~4&TRFFj49MH^^YJC54q(Gd zGP5d>z=zwV{Mc#D&2-av>9@#LSVI?cgIR;V_P6OcQFv9cHt5pB)Eve0JK`kYe-F4o zTks`pLUa6cT)Yc^F#xbNJcT@>VZo{V?dBAKhe>gER!j88aookC?^!*h`NerOIuLL2 zd1ziFr~r|gmOK{q7XlSy0WE7wlfQKv#^!50xEFnGrc{vr0S7c*n_Diyv0+y3tWZ;{ zMVHSYf5bJ{^_Y~84OE^;PWGVtA=@(o|32u7^JO8IGZh(?3Q zBrFsFcAS-4;~o@I3UF*l8SFGBS?XU3fYcpK+jm^YoqDJ`!4+@@i6Hkw>XkljY!*f+ zPfA~_uvTUGdbTjNDF%(Mk2!4m2(lL%0(nQSgLqoAe_Nh@jmM(vF`;D!6tYy)LZG4I zQf-hXB>A3RL}dE5)b^*ZyR6osLTmr~jw+Go@J2q27N6&ZzR1q^8MI+8Z;ol*Scp>r;kVmLdY#p0z zYHa-3a->3I1N8L-oWQm&lj*T@xRAF5_EKTNTM)4H%g!Zsf?9Nja>@zMoN2uSagIUdCog}4+fD#fK1UiQDbUJ#0nCDEoq z{alU?9jt1FvP6KbkUo`||6iZumplRy6Ttzv=6`-4gnMoP^8sPb$p#^;|NN)Vzd!Qt zbp2Bx{*|tO_sM@~2*?EZSFQZ3h5zH+`2RgmMi0*v;62-YS=r`y3j9fl%Zuea)bss6 D__yV@ literal 0 HcmV?d00001 diff --git a/spring-state-machine/bpmn/img/simple.png b/spring-state-machine/bpmn/img/simple.png new file mode 100644 index 0000000000000000000000000000000000000000..7a79bf1d895a401b2b59d4b093e770f3546bc3d3 GIT binary patch literal 22706 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 AC;$Ke literal 0 HcmV?d00001 diff --git a/spring-state-machine/bpmn/simple.bpmn b/spring-state-machine/bpmn/simple.bpmn new file mode 100644 index 0000000000..8ed463e9f9 --- /dev/null +++ b/spring-state-machine/bpmn/simple.bpmn @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-state-machine/pom.xml b/spring-state-machine/pom.xml new file mode 100644 index 0000000000..5393626083 --- /dev/null +++ b/spring-state-machine/pom.xml @@ -0,0 +1,31 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + baeldung-spring-state-machine + + 1.8 + 1.8 + + + + + org.springframework.statemachine + spring-statemachine-core + 1.2.3.RELEASE + + + junit + junit + 4.11 + test + + + \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewEvents.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewEvents.java new file mode 100644 index 0000000000..971fc5dde7 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewEvents.java @@ -0,0 +1,5 @@ +package com.baeldung.spring.stateMachine.applicationReview; + +public enum ApplicationReviewEvents { + APPROVE, REJECT +} diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewStates.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewStates.java new file mode 100644 index 0000000000..1df2db1f86 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewStates.java @@ -0,0 +1,5 @@ +package com.baeldung.spring.stateMachine.applicationReview; + +public enum ApplicationReviewStates { + PEER_REVIEW, PRINCIPAL_REVIEW, APPROVED, REJECTED +} diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/ForkJoinStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/ForkJoinStateMachineConfiguration.java new file mode 100644 index 0000000000..c55104a627 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/ForkJoinStateMachineConfiguration.java @@ -0,0 +1,74 @@ +package com.baeldung.spring.stateMachine.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.config.EnableStateMachine; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.guard.Guard; + +@Configuration +@EnableStateMachine +public class ForkJoinStateMachineConfiguration extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineConfigurationConfigurer config) + throws Exception { + config + .withConfiguration() + .autoStartup(true) + .listener(new StateMachineListener()); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial("SI") + .fork("SFork") + .join("SJoin") + .end("SF") + .and() + .withStates() + .parent("SFork") + .initial("Sub1-1") + .end("Sub1-2") + .and() + .withStates() + .parent("SFork") + .initial("Sub2-1") + .end("Sub2-2"); + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions.withExternal() + .source("SI").target("SFork").event("E1") + .and().withExternal() + .source("Sub1-1").target("Sub1-2").event("sub1") + .and().withExternal() + .source("Sub2-1").target("Sub2-2").event("sub2") + .and() + .withFork() + .source("SFork") + .target("Sub1-1") + .target("Sub2-1") + .and() + .withJoin() + .source("Sub1-2") + .source("Sub2-2") + .target("SJoin"); + } + + @Bean + public Guard mediumGuard() { + return (ctx) -> false; + } + + @Bean + public Guard highGuard() { + return (ctx) -> false; + } +} \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/HierarchicalStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/HierarchicalStateMachineConfiguration.java new file mode 100644 index 0000000000..708dbd3077 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/HierarchicalStateMachineConfiguration.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.stateMachine.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.config.EnableStateMachine; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; + +@Configuration +@EnableStateMachine +public class HierarchicalStateMachineConfiguration extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineConfigurationConfigurer config) + throws Exception { + config + .withConfiguration() + .autoStartup(true) + .listener(new StateMachineListener()); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial("SI") + .state("SI") + .end("SF") + .and() + .withStates() + .parent("SI") + .initial("SUB1") + .state("SUB2") + .end("SUBEND"); + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions.withExternal() + .source("SI").target("SF").event("end") + .and().withExternal() + .source("SUB1").target("SUB2").event("se1") + .and().withExternal() + .source("SUB2").target("SUBEND").event("s-end"); + } +} \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/JunctionStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/JunctionStateMachineConfiguration.java new file mode 100644 index 0000000000..e1bae10fb7 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/JunctionStateMachineConfiguration.java @@ -0,0 +1,60 @@ +package com.baeldung.spring.stateMachine.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.config.EnableStateMachine; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.guard.Guard; + +@Configuration +@EnableStateMachine +public class JunctionStateMachineConfiguration extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineConfigurationConfigurer config) + throws Exception { + config + .withConfiguration() + .autoStartup(true) + .listener(new StateMachineListener()); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial("SI") + .junction("SJ") + .state("high") + .state("medium") + .state("low") + .end("SF"); + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions.withExternal() + .source("SI").target("SJ").event("E1") + .and() + .withJunction() + .source("SJ") + .first("high", highGuard()) + .then("medium", mediumGuard()) + .last("low") + .and().withExternal() + .source("low").target("SF").event("end"); + } + + @Bean + public Guard mediumGuard() { + return (ctx) -> false; + } + + @Bean + public Guard highGuard() { + return (ctx) -> false; + } +} \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleEnumStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleEnumStateMachineConfiguration.java new file mode 100644 index 0000000000..4e11851644 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleEnumStateMachineConfiguration.java @@ -0,0 +1,53 @@ +package com.baeldung.spring.stateMachine.config; + +import com.baeldung.spring.stateMachine.applicationReview.ApplicationReviewEvents; +import com.baeldung.spring.stateMachine.applicationReview.ApplicationReviewStates; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.action.Action; +import org.springframework.statemachine.config.EnableStateMachine; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.guard.Guard; + +import java.util.Arrays; +import java.util.HashSet; + +@Configuration +@EnableStateMachine +public class SimpleEnumStateMachineConfiguration extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineConfigurationConfigurer config) + throws Exception { + config + .withConfiguration() + .autoStartup(true) + .listener(new StateMachineListener()); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial(ApplicationReviewStates.PEER_REVIEW) + .state(ApplicationReviewStates.PRINCIPAL_REVIEW) + .end(ApplicationReviewStates.APPROVED) + .end(ApplicationReviewStates.REJECTED); + + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions.withExternal() + .source(ApplicationReviewStates.PEER_REVIEW).target(ApplicationReviewStates.PRINCIPAL_REVIEW).event(ApplicationReviewEvents.APPROVE) + .and().withExternal() + .source(ApplicationReviewStates.PRINCIPAL_REVIEW).target(ApplicationReviewStates.APPROVED).event(ApplicationReviewEvents.APPROVE) + .and().withExternal() + .source(ApplicationReviewStates.PEER_REVIEW).target(ApplicationReviewStates.REJECTED).event(ApplicationReviewEvents.REJECT) + .and().withExternal() + .source(ApplicationReviewStates.PRINCIPAL_REVIEW).target(ApplicationReviewStates.REJECTED).event(ApplicationReviewEvents.REJECT); + } +} \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleStateMachineConfiguration.java new file mode 100644 index 0000000000..fe4e0f82ce --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleStateMachineConfiguration.java @@ -0,0 +1,105 @@ +package com.baeldung.spring.stateMachine.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.action.Action; +import org.springframework.statemachine.config.EnableStateMachine; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.guard.Guard; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.logging.Logger; + +@Configuration +@EnableStateMachine +public class SimpleStateMachineConfiguration extends StateMachineConfigurerAdapter { + + public static final Logger LOGGER = Logger.getLogger(SimpleStateMachineConfiguration.class.getName()); + + @Override + public void configure(StateMachineConfigurationConfigurer config) + throws Exception { + config + .withConfiguration() + .autoStartup(true) + .listener(new StateMachineListener()); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial("SI") + .end("SF") + .states(new HashSet<>(Arrays.asList("S1", "S2"))) + .state("S4", executeAction(), errorAction()) + .stateEntry("S3", entryAction()) + .stateDo("S3", executeAction()) + .stateExit("S3", exitAction()); + + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions.withExternal() + .source("SI").target("S1").event("E1").action(initAction()) + .and().withExternal() + .source("S1").target("S2").event("E2") + .and().withExternal() + .source("SI").target("S3").event("E3") + .and().withExternal() + .source("S3").target("S4").event("E4").guard(simpleGuard()) + .and().withExternal() + .source("S2").target("SF").event("end"); + } + + @Bean + public Guard simpleGuard() { + return (ctx) -> { + int approvalCount = (int) ctx.getExtendedState().getVariables().getOrDefault("approvalCount", 0); + return approvalCount > 0; + }; + } + + @Bean + public Action entryAction() { + return (ctx) -> { + LOGGER.info("Entry " + ctx.getTarget().getId()); + }; + } + + @Bean + public Action executeAction() { + return (ctx) -> { + LOGGER.info("Do " + ctx.getTarget().getId()); + int approvals = (int) ctx.getExtendedState().getVariables().getOrDefault("approvalCount", 0); + approvals++; + ctx.getExtendedState().getVariables().put("approvalCount", approvals); + }; + } + + @Bean + public Action exitAction() { + return (ctx) -> { + LOGGER.info("Exit " + ctx.getSource().getId() + " -> " + ctx.getTarget().getId()); + }; + } + + @Bean + public Action errorAction() { + return (ctx) -> { + LOGGER.info("Error " + ctx.getSource().getId() + ctx.getException()); + }; + } + + @Bean + public Action initAction() { + return (ctx) -> { + LOGGER.info(ctx.getTarget().getId()); + }; + } +} \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/StateMachineListener.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/StateMachineListener.java new file mode 100644 index 0000000000..bb7859c683 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/StateMachineListener.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.stateMachine.config; + +import org.springframework.statemachine.listener.StateMachineListenerAdapter; +import org.springframework.statemachine.state.State; + +import java.util.logging.Logger; + +public class StateMachineListener extends StateMachineListenerAdapter { + + public static final Logger LOGGER = Logger.getLogger(StateMachineListener.class.getName()); + + @Override + public void stateChanged(State from, State to) { + LOGGER.info(String.format("Transitioned from %s to %s%n", from == null ? "none" : from.getId(), to.getId())); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineTest.java new file mode 100644 index 0000000000..416da5f0fe --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineTest.java @@ -0,0 +1,45 @@ +package com.baeldung.spring.stateMachine; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.statemachine.StateMachine; + +import com.baeldung.spring.stateMachine.config.ForkJoinStateMachineConfiguration; + +public class ForkJoinStateMachineTest { + + @Test + public void whenForkStateEntered_thenMultipleSubStatesEntered() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ForkJoinStateMachineConfiguration.class); + StateMachine stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + + boolean success = stateMachine.sendEvent("E1"); + + assertTrue(success); + + assertTrue(Arrays.asList("SFork", "Sub1-1", "Sub2-1").containsAll(stateMachine.getState().getIds())); + } + + @Test + public void whenAllConfiguredJoinEntryStatesAreEntered_thenTransitionToJoinState() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ForkJoinStateMachineConfiguration.class); + StateMachine stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + + boolean success = stateMachine.sendEvent("E1"); + + assertTrue(success); + + assertTrue(Arrays.asList("SFork", "Sub1-1", "Sub2-1").containsAll(stateMachine.getState().getIds())); + + assertTrue(stateMachine.sendEvent("sub1")); + assertTrue(stateMachine.sendEvent("sub2")); + assertEquals("SJoin", stateMachine.getState().getId()); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineTest.java new file mode 100644 index 0000000000..3557a63211 --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineTest.java @@ -0,0 +1,37 @@ +package com.baeldung.spring.stateMachine; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.statemachine.StateMachine; + +import com.baeldung.spring.stateMachine.config.HierarchicalStateMachineConfiguration; + +public class HierarchicalStateMachineTest { + + @Test + public void whenTransitionToSubMachine_thenSubStateIsEntered() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(HierarchicalStateMachineConfiguration.class); + StateMachine stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + + + assertEquals(Arrays.asList("SI", "SUB1"), stateMachine.getState().getIds()); + + stateMachine.sendEvent("se1"); + + assertEquals(Arrays.asList("SI", "SUB2"), stateMachine.getState().getIds()); + + stateMachine.sendEvent("s-end"); + + assertEquals(Arrays.asList("SI", "SUBEND"), stateMachine.getState().getIds()); + + stateMachine.sendEvent("end"); + + assertEquals(1, stateMachine.getState().getIds().size()); + assertEquals("SF", stateMachine.getState().getId()); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineTest.java new file mode 100644 index 0000000000..d0c1225c9b --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineTest.java @@ -0,0 +1,24 @@ +package com.baeldung.spring.stateMachine; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.statemachine.StateMachine; + +import com.baeldung.spring.stateMachine.config.JunctionStateMachineConfiguration; + +public class JunctionStateMachineTest { + + @Test + public void whenTransitioningToJunction_thenArriveAtSubJunctionNode() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JunctionStateMachineConfiguration.class); + StateMachine stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + + stateMachine.sendEvent("E1"); + Assert.assertEquals("low", stateMachine.getState().getId()); + + stateMachine.sendEvent("end"); + Assert.assertEquals("SF", stateMachine.getState().getId()); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineTest.java new file mode 100644 index 0000000000..1fd7bd85f0 --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineTest.java @@ -0,0 +1,33 @@ +package com.baeldung.spring.stateMachine; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.statemachine.StateMachine; + +import com.baeldung.spring.stateMachine.applicationReview.ApplicationReviewEvents; +import com.baeldung.spring.stateMachine.applicationReview.ApplicationReviewStates; +import com.baeldung.spring.stateMachine.config.SimpleEnumStateMachineConfiguration; + +public class StateEnumMachineTest { + + private StateMachine stateMachine; + + @Before + public void setUp() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SimpleEnumStateMachineConfiguration.class); + stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + } + + @Test + public void whenStateMachineConfiguredWithEnums_thenStateMachineAcceptsEnumEvents() { + assertTrue(stateMachine.sendEvent(ApplicationReviewEvents.APPROVE)); + assertEquals(ApplicationReviewStates.PRINCIPAL_REVIEW, stateMachine.getState().getId()); + assertTrue(stateMachine.sendEvent(ApplicationReviewEvents.REJECT)); + assertEquals(ApplicationReviewStates.REJECTED, stateMachine.getState().getId()); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineBuilderTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineBuilderTest.java new file mode 100644 index 0000000000..cdd1e951e0 --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineBuilderTest.java @@ -0,0 +1,35 @@ +package com.baeldung.spring.stateMachine; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.springframework.statemachine.StateMachine; +import org.springframework.statemachine.config.StateMachineBuilder; + +public class StateMachineBuilderTest { + + @Test + public void whenUseStateMachineBuilder_thenBuildSuccessAndMachineWorks() throws Exception { + StateMachineBuilder.Builder builder = StateMachineBuilder.builder(); + builder.configureStates().withStates() + .initial("SI") + .state("S1") + .end("SF"); + + builder.configureTransitions() + .withExternal() + .source("SI").target("S1").event("E1") + .and().withExternal() + .source("S1").target("SF").event("E2"); + + StateMachine machine = builder.build(); + + machine.start(); + + machine.sendEvent("E1"); + assertEquals("S1", machine.getState().getId()); + + machine.sendEvent("E2"); + assertEquals("SF", machine.getState().getId()); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineTest.java new file mode 100644 index 0000000000..1b442bf994 --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineTest.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.stateMachine; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.statemachine.StateMachine; + +import com.baeldung.spring.stateMachine.config.SimpleStateMachineConfiguration; + +public class StateMachineTest { + + private StateMachine stateMachine; + + @Before + public void setUp() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SimpleStateMachineConfiguration.class); + stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + } + + @Test + public void whenSimpleStringStateMachineEvents_thenEndState() { + assertEquals("SI", stateMachine.getState().getId()); + + stateMachine.sendEvent("E1"); + assertEquals("S1", stateMachine.getState().getId()); + + stateMachine.sendEvent("E2"); + assertEquals("S2", stateMachine.getState().getId()); + + stateMachine.sendEvent("end"); + assertEquals("SF", stateMachine.getState().getId()); + + } + + @Test + public void whenSimpleStringMachineActionState_thenActionExecuted() { + stateMachine.sendEvent("E3"); + assertEquals("S3", stateMachine.getState().getId()); + + stateMachine.sendEvent("E4"); + assertEquals("S4", stateMachine.getState().getId()); + assertEquals(2, stateMachine.getExtendedState().getVariables().get("approvalCount")); + } +}