From 92dd5cab93d08148980547f47e4edab273bd8575 Mon Sep 17 00:00:00 2001 From: wing328 Date: Mon, 25 May 2015 11:44:08 +0800 Subject: [PATCH 01/72] add restsharp.dll, update compile.bat --- .../codegen/languages/CSharpClientCodegen.java | 1 + .../src/main/resources/csharp/RestSharp.dll | Bin 0 -> 150016 bytes .../src/main/resources/csharp/compile.mustache | 3 ++- .../client/petstore/csharp/bin/RestSharp.dll | Bin 0 -> 150016 bytes samples/client/petstore/csharp/compile.bat | 3 ++- 5 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 modules/swagger-codegen/src/main/resources/csharp/RestSharp.dll create mode 100644 samples/client/petstore/csharp/bin/RestSharp.dll diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java index 9de427058a1..da67bb75785 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java @@ -46,6 +46,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig supportingFiles.add(new SupportingFile("apiException.mustache", (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.cs")); supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll")); + supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll")); supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat")); languageSpecificPrimitives = new HashSet( diff --git a/modules/swagger-codegen/src/main/resources/csharp/RestSharp.dll b/modules/swagger-codegen/src/main/resources/csharp/RestSharp.dll new file mode 100644 index 0000000000000000000000000000000000000000..c1da1b588cd958eec6ceeb4d5be40b3c0c65b17e GIT binary patch literal 150016 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≠0S1>^uhm zyUExGd2DWuK zA)tt|3R^!I*0Ac(IVM$MC$rF1(}LZCiK;jDE5K~iE)L?neSH!3OGP`2?|$ZB88>WNTRKr_D60@q1Vlmm00n)L1*HwacP-iQ!h()m1d+&Eju0>$->m^509>pA zAppEb146`2%Y7khu@4@EOj>rOTEqFb#^oLe{ZEWbdYS%SWVj7Kq7yJj1!x+V2he*m z3;5p}mrD_H2jlWUfd7ec`TsxL@)A^`*p`Q&h|0DkG{&C^w&i;@>!D;7+mg^2fBp}) zCC7%J!#vv$?ZuK6FN_IKqaV<=U?7Tx$VP7iIt zwP0?J+c>rgN?&+ZY-U(Mi>_p_o;lDtYsCZOmzJzytH%>xG|c#q1n?RF+a~f zY{||IL9Dt|+p$p4v;nKItHM!x_$jlMF-(6hj2kDrgu#?u=pk8e2fOe}i9wbJXcs16 z7w&^BM(x6N!lLa$m6MQ5?7}p{X~ULp?C-=bRDnXfPz+REe&OGVU6=?NUKOirN4s!u zW-_!3b(V;Q8Ee^v3D||2K}y!L3ll7Gn9h48ow2w8{dmZhT^J2{n1q~Q7w!>;%x801 z>9}gT4tH2oz-*Dx(GgMz~WgfGGm5JqM9Lrb7m0bpJ|H$lyk6xo!ss`t!*4msb%7k2_rtJ@jaFj>)E;F z=m(G!5;%?=I~A-j)wi3x}87;V$OJ_zw1zqA_ z(FcQu{o~8T!}BVoWN1YvLn}HNTG7e>){4HGb=k6_V@CIu9o4hRF7>YzRoRo6w;2Z_ z|BW9&&a}PBni`1*2;I}6U1AZz_HHsnG-VFo z)3V*6FS*9Ep{&W38fo%|w!65avTicOWF2RttOXIHoVI(@_21a;&#|C8*zU8?82Y8_ z!W`Z<_JPhXMLBwnC5EBi0cq?4?{p=VbP8_ZgEpN4-qi?p1=*J=%=>vVz-o+_jV=bJ z&@`Ltfpd1(^Ld-+U)f#}|G17n5*^-bnTIuWxq<;vR(^)|%{T1~V;RDjHAl|EtDRfC zfEHB1R34B$((#*7r_Cvs?ElU~xVIo&!5h03o_!g-8FCGJkg?m~swMolK`Dez%f7Cw z-a1K!`?`47caF+;&)DsZyJzf^eB57Ojwxe+r3G*N769sv9VXB?9uba{NjS$Plpa`a zS8w4}6SjFo#l_alDli{msTqx(u#PAvEQOUE8}ki(?Bnc&ZaKgxXqQj-@QO?mfb@L?Q* z2w!h8Syzmkb&vRQK6wKIRk46ARgV?xYnccV%!LU${%Rdxa`4waHUeOMQwda!NPL#D z7SBVa-qQ6;k)!Y?oy*Vku!dg{9V4DR=O9N(p7%NuIS4vBRIQ9f#ef~yfchp z-+*B+5pwak)ITqW-&q3z>463Et~1CzSIBG7SnD><#a|VFxn%FOHw;60><8dP{2hV6 z$_c6ZT`0P$_u(4>rRra50o)cy)gNgA;{t4L0+o8IzOCgtEmeP|v_UxMOTt+;9nBI!V>tCQBv7{oeWT>&F`w%V`?q5_|t<`x|el z-A}2HhmgC&|3!V2qV?giKJXIfot|6@~ z;j5}jWikc6v5GuHa|-$7@HE6^Vv@*4oOe^TIXS50&}3c$BQh;!hyRFb;Vm%Y9)1Zf z;aObFVq>G=bl4NC2T_MDJA7}a5MZ?tcii-calr61QpKTVh-Z(XIfZPDyP1@uf(synG}c5I?Gl)5SX|+Jm0KjzT#EDe^N&S?&83PV(!D}1 z+6jh`y=wnI@!Sobd9TCsKQ58+f|}hy^%t@_hfh%Xr!09C4=K{2P-b3ZH@}vQD06a0 zNhPC-?BPZ4CzOPmQA3oKvoZIcj!FCO%w%WIE=@iTF07||crU#OhNI!cnyXjsfTst~ z(!3R+7n)Tq2jJWRNT;-XC{cvA_I3Y@nrlfBuSBvtarb`yA8)+j1j9(7Fn?04t|~>S zKz?Th6UmqFG)prF=9ndapk$VI9q2Jj<$*4wRFp)AQdX%V3BWaPaEe*lXKunQEu1&WEFCu=)X9VR*))H-UERejT`+&v z#H?DSd12Pov*KzFv**-|DuWxA!9>m`K;>p;)EwhokjPspo6<}sJU0JGIX*VY5WST1 zV;ov`*NHgED|bi+*p3M`UwwU8iakX~V3h`A`Hy7C!kp)B93kRAAFI+{1FM?eIIS8n zXX+XB&%HOmH^5exGI#0)VrWBAY!)$&E)l*eu}{RYVPZGMu>*-=WQc}6lo*sFimfCD z>nMt?CWh=rv30~?J4LZ`iNT7BViywoR2;jU*d1}~L&QEE$38~v&Ny}pF&+kr$lxww zcg3;$h{4P6#<33(qs0)Z zkDG{nJ&xT;?BO_eKe0#R*dxTg5yze;_RTo<6Jp%_ht$D9X^tt9qT99u&Si{sI-XA}Eg9J`3v z_v6^*#C{ORwh((Jj@?EKOHmdK_Cv>>qLLd}3IciV^?gW6u-&d>s23vHRlK zE5yDK$Nom_{y64jfqgNKbrSnh9P1(WI#IcKseKU?-PV8H8Yzwg`;@BO;o{VGn z5&M1|dw|%i-dNclCDtFuo*_0E$9_g^D2}~CY;hcWo!I_y%xwqOJu{YWfmkk%%_24} zj#Y`xietmXc8_CAiCq!LjwE(v99v23195CMv8&?PdSX|{u}#G8iDMTN+ZxBNAofHY z+d}NgICc}Ur{dV1#Ga00_YvcDI}x3HgqRt}wi2`A*z?2^aqJhwl5y-cVs0GUPAnD2 zyh*^)acnZNNpY-)ST2suBGwVd28b2o*q+3C;@DDR)8p8Y#Ad{?Rm6JZ*lJ?C#Ibe6 zcp-a4rW=Uu8pqBjR*qvA5v##c}L!#NHFf?8(4B7{?|PyC#m!Aa-*c z!`UbFopEfCm^(XGM~jK2;@C1`UL0FaEFH&I6WcY8ttVEFW1EOQ+80arLSiTN$FM7i zof^kJO6>GFb~~}vaqM1TrCAZ>dw@WH1o$R_JtM&51QthtrvdaH*%r&wi^RA<8sYm5 zv6JH1--w+Y$J`vSbK_VCu}92UeA9?MAII>*8v3JnzduOKieq~cOU1Ee#4>U0C}P<- zwvt$T96OEJq&T*gSU!%OORO`FT|}%qj$J`)N*wzrv7R_~8?k9|>~3Pyb0$KX;R9B}gRe##O&&J1vhLC&1m+#fZL!uq78)^4$RBKPrOL)F5~ zlKX-Wdk>W^H+3bpZ{=D{brf4|pW()mm+)fIlM#=yTKCLA1CQpqr|flLId~T=zIP2} zO{~r;5*r;>Eh)L2+@`iU)_9HmkYXD92E$wm!(HvN#gR>w`j%V-0QY(?U*pU@A0EZ! z;#KM!SQl|^9NH~sPbE(kX!r6SzYYOp+^zvEi9ccaZ-EhWT zlXuq`$0Ck`XIsnDR;Dt=bg%T+Bav(hn@U|}r{|Q^^6*vm!Jmd_RZO0L;rq_5aOH5T z7BatJKEkD*lvr3Y9Z$|~M)agAgJoa~+gQOeu)b}*ZE8YMTRXVev&HpPm!F9Z+SsnG zi``iTxAtw-9ee5s0ZNpypb}iMLQP!>Wq21z)~_Av0pHH33fSc%h2CLrH01zLN@fazYhZ73u{U`m$XEland6)4-&m z7K{Ib1g@mIIHg{-MN~=S_`ZFma!`pWS9kAzQ5d#OWVSt?+0Jyh-@b24ef)Efqh=dF zn~n>`mp#KG_6&2-+|V<~27|wW460pT3&9=Nswcgj4)J^cWJ}$0?D&?ts+4d?eShqz zvkWLD3JICuMX6HXP;biZUNN`FL^sjxQ+(VH#YZx7i6`=Qs(X1ByJkw1;XeF*;Xb_X zx6V^phHg8?^~m$_I?w82Rdu~mb8}vGA3SNWpryXp{Yi26C&k^L6nB48-2F*m_a~E* zt)m*Zid}V&^WY=0OAL`gL|%Zyik_S_z$ZIQ^qT~8b|JvIL^NtSxd12L$hZI*Rn7ZD zs(vm%Q)|C)A@JpAMz}8DITzlwXvL(3Fxsj&^qI!WrVJ!It+No}J)e0T8i!Y&w{5bZ+GDYFZP1xvvcjlDFl_~UPCy9z`mi<(Zu?PKw=v> ztYz`+1b2D8Tl^eu} zmWgl}7I|VJ#_HlAI*t(FOuOfH4Yifs`01Cn?+m_}47aJ&eJ#1>Zx#j)7OR%nA;IVWWWe-mB{o%py+xbRl9~ zy1fw+eD0$|0cDJ<@m`L9DHA#8AG)lAUvNGwNin@jOn}@s1#};&urJHvJ>WI}?X_aQnlLc=Qev0o;-R01_^{5^qPF ze-zN_R5LuSbu?YLRKY(6#0C?2mwTo8#S+6fm1!Ld4<3Cp`01c;;|KJ1e4i%3+7#*6 zNn<^WbUS%|sA#-p-~=xydJ^g96z!6JO3{-^|47ju>F+5zL;44bwn=|i(GF>>f1$;o za?fHz#dD03#FK4>PaMaR=NdlIhBm;T_a|Ry*4IIumJ1tH=w5LeXCVtfS3QHq`X+=Ajw55%tX~3$ zU7sV*DfQLz?5STN&#CqM?)3ecT<#Q;Y&yZ{I9JRSkWOVk~S9Yl=oXDts`;ypeI6r2INdwxT?rbMEkD%6hO z0k1Dcd2Am$PsfWNx5cIE6i_1wbA7?jo;0g2l+zUbOrh zSXXSj+#!7%^{RQ+G1NxZwrJyI1JfGOP+b3THnM`R(#V{OhujLK-s{lIzY}m8H%S%e zdC9^S{}YJ4dNQn+!*KhQ3=)O;OL!4gN__-?29{!i4PpnF#6W;4H6GdQ)nSq(-CSbx zS*Rzl20(CMd-&mvPvK@*Oa#0#k}4GC=#(A6CS%enet%Eo2e(gI{`JU-ej6>5L9>1^MJeL>idkO;NBt5JE@G`;9e3VKCmSrMS6*53KN#n4IUgtgY+gbx{Dbvp z0GR9%F=ds$d@1VS4Ag0`Em1NCbeH@6{9*003mIS0TY-=LX~=W_gAfWI5?$8CFVlTJYZoTV|Kx5h9u zir=S^lt-A5Xvv}@37Z0p;=Lmq-o$LM~yZru}n<9U_~)bKYB;k2mp6zKnMVz)_@QI z?$m$~06wDuAut3>$rhOPpP&g^{%@ERT(87je~r1!t|;eH+{J47zYW86h@W=#v|Ni! zTQ1NISzAs?QRm}Oa|GQmreh;$A-4Y-W0iLgZh?H!^T~TtzkmRF{?Q&KQ!Z(aGEApu z`b8KxY12yje?dUcY`g{TY|06i;h7r!9Ey(qS-rCKOV+|h)B?L~C&2vL%b2b?LMH!J z1m8A{OOLNXKy}PFIEOWM7u+dqC2=#0ZEnLKQSD$Eblk)YafTNHHLSClkcY; zf-8ccQ*HbI0FfDv@YNkC85MMFC?xvPT&ZcSVgdj1njAgc5NkMVzMp zcf?x56lnkjA&lreuHK_aq-6L>kD{o2#=YvQ)!kYAFG+CE> zxR3ixI6;VKy&pQNqFJslf&E(aE>6>*#L%ON57Vt_sQWRH85J6DxkaLeUkyV`?YRkG zhmwT+-UugE#Aus_Ap@&=`>o}0MEYIEu6Gz2(vdnuAI~~O?;JJ=zKesN3SX2&fAd?` zm0Vm$hMa4T3V(0`GPz*@iQu|Q>U3}rlCMq=HEW6}uA9cxPen|1Dmzv%j$qlaHdAKG z??NF(Td(3Dbjic+RR}dcSc96@=MYTe*;S@VZc&ye@># zJuVfQ;4^CBJ3>zIW*}9p=w%t@k~R3u_S@l77&gA zZ*9B=Kmg+hcC=6C0G1WZpPt54IJoG>p3t9-WePfSbYKm-QeGT(4;#?=arO>RcE)}m zJz;a)gZ@V@01*Pfy&4b#z~?m}1c3WAAOwIfXg~-6_iI210AJLA5CFcU0U-cDEW5CXcwGx>+%$$!e;G8?c_aW^!CWHvB| z@O(!|n5MXbLCEV!c98U8sd|m;@iTfiqBecJ83c4U{8Fd^j32qlH-I(7u10jU1J54z zU0CnH;Efx5Oeer-t~fD7giBmLV*#&)chjH1lmE;Srcy58D7nRB5f~d7V!Uxe zf(K~o7+r*U5t$#>%zHGM2?-u$K8nm(NKi5F*<>apc$9e+nZKc#_i8c|5c7fXM>xCyhb31H%11XVd#rpesd- z(+n(DGeqdI3_$o<(A%P~>*{Z;WsH?)s4MU*4)Ue;79+M>rn1--%MAnbFk&q7gQQ(pf(YM)ldq2^1J;j^ zE)-TGYe-17kR4u3c7OC@vT)Z9X{zzP!&tUb<%Qqvelu|X3(cvFp2Cw|Jxueq^lVSaZ$%GW0QR%F)Q&lJCp6oYKe!GtgT9~i zZHoRP=?^RVOQb)d=r4ozkK`zLlLEd%&l?o|Rnj*q`T^3nkS>Z9VFh0Uvha0CO_9Na zaN`wT^fCq(^Oiuy8$Qks0-snzu*Mnq;r-taF``4@0R45+hbj7D(nl!z5z=o}^fyQ! zt>|x(K337+BE3S5AS;`fa3xCqSYY zoSiJH@p8_t+|F(hwt^=a28$th<+PAbRrbRDlqr7uhPe954c>76B;st~bAvKTbc2nc z@D<+R9C-#$F)eKS@a@i=i{m3-w8RLFU-k@T*k?Di4aoOB_+@7XFZ~ z@jd*>qzG=V-yMwSCRB@E{~p?o|1{D=R|YN*);T^{2qL-`{e8I6=m|$wihaTv3m4h_ z00c}H^+}&0lz|SeWBA&^#Snim^x;}a)4`>Xrh_XeO$V1gR0LRam6Z?W)pSYZQl0|J zGs3p2R|OU#DVmbIGf7ou*jYR0c@ucRI;!kFKIFp z5N9IR0^FB>xLV`z`hsgYG&Ae}unULU7=3~kH9nHL7lbMjMj zc_GIR+A!Ft3)fq!I6>7Mx2)hrL{Hu1!a($s2T(OGVj;?KEbK9G`qP6`=8*g0iDh-f z`FC{BXs0rGg^M^cf?2pXM9q&>BIsS4L)y;lk&2NGzY+3p=49bC=|7p7g%c~&-*L{R zrer&vpmEwIvpEvs{A*`3yeW{6@R5)?S#+MIrd78V~}&Pc$F| zfS+nWh)Co=(;h;A6ALD)C_+RyU)CN%fb-`X5JGdF9h)WI4s9_TG9SEyEeyearGp6p z;MW=u0>E!HAjE~{2o^0c-GYtz3BJMzAOwI{G#~_k zS2Z96fInzJ2mpW7fDizFsR1DXyruym0Q^YfWK%!2mpW8fDo%>Vu0{C%7Cv9;8)Gcbd-{xq;U$K z??isK&ZfPOAqAJk{t%MhEbbq((^LSy6utr@1kwoqlGBC?*yVAs9NCB18?b;qe>N!Y z{SciKM~?%X*pc~cs~F(BwXl@McS0bYTm2j}M=&Ww?PEH~#brzy;lP~G_WPN%=38Zs zVDe^?zY8i|w!+h&m0X#-oY;IBfff;)VS<0CHe(HNzrHjIiBy+(htmgdd#+XNby)q5wvx z`bIs?Rc+hlQT~fiepH=*2vYYDLn8PEC8XP z;Ds+?js6x-#~%G1ALi)q@i3hc0kO~uSL0Ru1ieTun#do>H-g1i{Jw_YW+JSo-I2z{ zQs3}l8h^$UY5au`bM&uxAPoVxJDA?8G!ntg35ooTj3clE@cTM`bs{O*jOvzP^oSu=5ktaBY1JLNo|lm zG+~2Oj?mP)998H(uvT4ctzmG%Tq8ILF)5DO;g{O*8E1lCrKA2;Z+IsqE*9$p7^U zChH+w!JJS9>kvtQxZZb9biFTJ##C#VyBUYQOU>K#;B&tvm5U7(1<`mWyMtuw3zS z%BLuWFX9y>iMMlm8{;WJ=XG3{Gp^BST$?7wb-u(ER$LFlv)(SW44#qTceD0FLAfXm zb8tRMX%N{?ukjC90_nL7VlZ zB+MoCs#svKgXqd86@2lffPaYBOosHh4JK-u5O zw^s_ecG=;`Cv2{+;>3+wU2Ip9`Y|Nc4oS5uNridH>J(0H=7G={e^egYHODFBz$TkF zPH2ojKB`l`3?$nZ`ANvbB-y~o|7?& zDSQhl5n-am^NZS&OnK-p~$ZFNcn#SAPW?#{k;c#jiueQzZ#N{MHZ!~9LtLe|0 z>t|Z+#JPV3yVJOWeZk9!7zSqWF_b2F3=YsAB`xRY@opk%IX{nqm$aOpw}a1;{;}f! z3~4z(ZwH)St26U<@M+R=X5J2NCM{>?q1~kA%)A|3Pg>5*+rh_4%b9sA!1WZ!30K-x zV@OmMLi=xnKA`)57M_g~et1SqcKxQn0a~{Brjni#Oy?uOT2u3Ti(i4BM83CZ%T|Wc zb4T91!xq6^NFnP4&meHaLWjlXmaJj^BiiBkA~E=s1dwS3<`z zbo?Q7ET`kO&>`D_e-0fh>GRjnv5Jnrg^rWxcs+ESLdW*daT*<%PD|ca(_xAu=wZ>r zO^;dJ^vK{Yabbdb+u9d#P@<#yx1SF|3b+Ftsd(j)4~1<;i%p(9rC7sQI|!4V%$ zF}@CmzW|A2dJ??A^pem^&_5=Po{scSNyDIUFUeR56Y%{P(tJY}uGp3)U)_Y+^B1L7q3W0obe4B*l2asP(3yzfR z1uh;uv*H*h!S9{$`#-Hu;L|`{h&UFpHLw)y`A0Ke1s)RzkHI7stP{|BYjI-7c+egb za{llt<{hKmKb_KhYD({@DZMmZeA&9WDv&WPSEl!->mQG7VZP_u0X8i?nO5`UA_bld z{>IArUy*%Q%O2ZTP1&b{39_GW?7d#ep1UP4up1(QZ4!suCZWJ(a#`M&Zrgt=G7tlf zY6AFd*FEEK#T)x`!I45$1Wfm=%Bq| z9<;W+uT{`%Od4n|I%%MLB1g|eVCqC*+C*T=M4*+dlx5$RIt3xnN;U*q$%a5H*$`+Y z8v?Cl1z6lHEkEv!Q%=oPwOc2u-8xO})=6r&PEoscg4(T%89c%oi=-F2o9Tt_W_qE! znO^8_rWd-K>52PdWxn?erR(p7?bz5A^}NXpzJ|0d88$G~LdVp4%7@rCWyoQ#$I*rz zA|FK=XdM6Da8M`z9e*Oq&oxffn&qf_x2)BvbWLLp(!Yl3S|Sk7*{~jiH-0ENDOoe0vsl{0WGY|L}T7o-IYzg~Jt{TM(_;s31Q7HX#Sm zru@r=oJMjp$+4LTCpPX^;cQgFK2At*|8u~&JoA3CTK?^H_TyzM{{y7Z@xz6C|CA;KDt!wleA!PxUD3|3a~8Ew##{u%#veQo zZa#ja+jNwzn&)MV_8v9QV?S~L@DH;Ou+VL!akQRMnex&CEBtQsP)<_f=QcJD!V9q7 zvDwRPV9$9c5q}GdfiBTb__qU4?gQz@H%va+L)VLe%=0x92$@K%7GbWgoEXY)+7@e#)3e;R%n_W-O~V30SA>G-ScYx?h#AU1nT z;KHeBD+t->5wd0E9Yjxl(`M4?@jnhv?z9W!e}pb1#dd(Xrtwka zW#Tuec)fRJ9d1KUZpqk}pII&9r!c=g{4S0^h>TY3LZz*UFY)c8J|LdA@lmH>Hx!g- zp{o^4k+9Y8RrB>ZJ;r)`JpCPL8M5q+b2IAuI(TpW24to`7v2_~!~W{vr6$Lxg1l7d zUq^3~+Ill6E5IgnD93--hIO02UP}9)w|U`LZC=DivY;eLvRjd8x6Mt0RRgSDu@u+ADj(9_6MItq-uYVkn)ho>11lV>YzdZ zC~H6n02K`g0idb@Apq1gAOwH`4F~~Xt_FkvFh>JI0GOu%App$RfDizNAtcGV5NMO8 zaTD6)b?oOB!jJ1okD|ExUFmO35}{ zCoS_nGkBV`%=^sX`=rBnr5`8#UHl-Pt)yk%X9iy<&B>pbY!88;=@vdmhIA2yKoNJ- zfDiz7*MJZJ7HB{S0B_QO5CDcXAOwJg8V~}&A`J)uU=Ixl0boxJ2mxR(4F~~Xu?BZI4i=>X_1zpqc zfPb(D5Y-(w9zz`1TIdGc=)n(c37nDL6AZ4bpi$NL(K!+Vz`hy~0>FM65CXvd8V~}& z0U8hj`P~aipsgNA9RBiL7Ip)&pXB$kC^IboOnI6k2k9t;K$xW(5CXuPH6R3lWf~CT z1E&8ddzpeifGBZ?{~K>y;6qXv=+37ot6@TK(V>JuGzV)y2mps@KnMVbYCs48hiO0v zwz-2*AJ@y6ybIFdH@Ym0y*1FX8IF}z8KE&7mnm#zCbCt5ue>E&){g5j^5b;hB-k2d ztK1YAH_ZIS%>QcLmHLa|H0v!NM9ld-wAr|Uda;;#q0|5$1pXl;kV*PO7cBE2) z&L+OBftc_Tj=zxExeYmJ;H(?AKdg!DSw)UA>E%B_Xhe%W_jHDS?)Vy^WDh)1D>-Z925@^$b*_IP!m9Wk$ray( z^QuLEso;#+kzDe9EsvW8jAs$z@eoh%B@5S_==JV;^wBpv$3>#zJCNS;rbjET;4R`o zlMwG{K&Kj5JL5hoPYHWmJL49say*4Jkl-4Vr-lXQGnk8dDN7rL0EJV%1A7GQ*iRr& zcJ!O3V=K_!WID1pf;A3D1mlDR_pxPP89PpMEFlMC@x}=W?k^z6@tR{Fa$ptD8z&^V z|0Z&*)ExVg*3943Rsao8ZNxHCaP?w?3NL`@GLOk zqdNWq#K@~0o}soU3;5QJ$c@K`t8<{@Y>jG@151$=e&mG+)+JNHt|T>sCEnjuSe$b<=FdT>n-L3ZG4s&)(Ojfxs%ISIg&;6F(MML7Sao;f1d(dY_!r zXyb&3O=S2M=t&Oiiaf{d4P!-_#|~zq306l{$B>0_PPghAa+L$|A`4CdPffm)zfN&QpI4Y?ZtDzproR{6nGW~U+l{$Pdlc~d~`*T}$ADn^ko`X+<>06?r#cc%n#$v$YfpC7<@gT_9K(K9f1WFrJpmu*EGkPnF?ptO*o{IufQ` z*s|ex#1%Y=#E&SJ6P@@`V;z!^Z=34SXCZWl!M8#@r00OoCiBG-RjwIRg1dU2WG3Oi z9c1~^o#zJIeb_Uk*6kvNgWO)eB@J<$zxRWJcXmnt4 z2y?8Fhk=apN9HnVpmG+Ty=98JBB9gC1GFW$1|EmwuW|-1Pm$Es5_x0{5DE_n^hH(u5w;;9r^1G2-W&ZNA$ud*bnJYT8ax z#+Fz|DOH#ZVd154ToRB%(xjt}Vj4Ll#QMP9CZVK5Aulr<0cvfOEyMKJvx>=I1V8MW z9Phw76_Tu)PPu+D75*Jy*(7tPnc%q%JVno};uT2D*ZFZrE7`$7Z%3dbDwfrGM01S` z28N1L)?+=ZQ#Fa%4qrFmfM#)j*{gNf?0)@Chyg227vO=nsj)EH>7Pb=Rpf3rOCWXU zTNGEU3Ktu#7ioVIdF{n_l?-lcV`#yf2^$b0zQl_=O2a_~uOl;E{|u&tFq|X4famR$ zg&ZuB?^%jfTF4CF125A>Ka~kDIxMYR@?m0f2*_QLO?B^$Z9(veKQ~BAD~BdIrIqT+ zPhQGYX#kux)ZwU`zaS-?ydi!(@C{^6MVJo+c*;<_Gb4iGI)&0YGI|kkI>7o+(J5sk zpo<+Xtau;+mBYRF#`I2G?Cjs(h0J0VIoCKD0>ISMZ{XRFtEkqR)-t~i2gH@I3rBXA zaTvMDP&p*o-EzrsWPcr)v-W`@cNkSVIdwnObCs&2()_<^Wj5PlG@kiC(AAgmDnG#Db{db^=vox_*5lXDZ%`|Sn8A>_s z#J#x`GxL`~+cb<%$MqM%-htRmt8ZCf9@j%2m2<8_`y2iyIu&afZW-MJT>}mb(i`i# zN9B@N;hy4IL&;)h_;&atp{rLnc`?xod7*npm*EEKiHRg6k?KIN@jPNo?B174 z^uB>EWA|y85r_8&<1kW4A*E@{kE-l~suhdA3?}~^ZrKVx4`ssPwiaLIY>BL` zI@y%i+R)4yzOu^l&jV5AO9JN#a@b0$k6yZ%shpr*1kd71 za3I)|t7Q_h0jKy=N>Y@but3ihob!V#1Wz3_1%X(>%R&k1p&)QW9 zIZdsirpYgBn4GJ84*9g}UNaulkz_Gj>BoW~^Xk+xb|hnFQWdvm7c$!h3i>vMC%1K` z)Y1V=7%UywYU#kPx3{9^q*cvXyNtnuWZaat`!MqHKgfp_F>sW*h)^=Yak{ z_TB@!s^WX}pE)!4=HB$1gqz-ggoK2IPH0LXga8R95UP{}5KxdvQ)34<1*VsX7JmriVYoj&JLNuuU3xO-Xb%oPM#bAiK4?NKq#|fXKYDD z#<0<76A3oxfCE;gGAeNywK9gm)uoKk5oii9DWg|iMse__Ic4HC@C!7y5Ocu`$1{7i%Lv(R48&$osx^Hja-yda^b9`Vx}U3 zpS@~_(Xd4b_YL0h2_xZRjVnfkEh6=QhtUJHc1SU45kaedR~@bIt&F%oJxV}5WHyR< zAVxipcG%v%pj42qO+*J3je}C-Io4rtdNsTsMB8xYA@6~G(Rfg)6YOD%JA=j(u-54F z;!${__FONi_Ub)`yzdBr=WWxmWpMLd^E-I(176A)2g+*j7LqI)4=(tyGNg~szAb_K zUZ@i|7f_G2z19C-9_p=!Hu7Kvs2;Z+hiEu@3Zh7^EfXd}UjC*|j`SEk5DH1{8J(Lj z2~2QnoqMJwLQ)={X%*o=J&bw?&op@85D&Bs@=UXmf|@Eo9>o9MQVkQssF_0LLHysP zNybPHz%-~0AgIeA8~S-Q2uhLGcaIb`$yE-1?ubjOTSXy~ykWGb{s})Sd3vV7t(~51 z>cbClOwBjmGU0WogZi_e7G)7E&OGgNeUu}3ZlF8}bGyo7$kZ5c1_s%J?A9f=pkSK> zSu`2j5Pw^l50MOotrQ*zPs^T%XaXz12M#LGeii&`V-E13oiYRdzX)0wC0~OOMVHWB zK@HW1U_Z4244@U%0BVEzaSP;AQrxgff;~}2!8WXLCmn>I|I^! zIB6nT`aRqo!q-0_gLaicF$`A9;q}9)F3}n26BGy!*U%#+L*erWk| zQH~COKOY*+76Lg6(Q{71WXN%~fP=A+5Oplo8IoUgG;N^mAl#TKU9f7=P+O?oW?Nzl zRgDSz->NY&4%}W>nF~t_w}q+91=@TKTOe$}Qwv^&3XBI8W$6?&VHo5mOgEt~oO`A( zG7Fr`ITdn;$G@po0;R)>wFXCdb2)1|2w+%mibYE9gRo+UNL58B&Q>y1>_bddU~0q^DUh8$)ZTPQucgvWGcK#}2?uEDR;{~?1{(f`Fb z@Kv2<1SQOcbgBh7Hl$$KO_+y1uu}j|xTWmb|+xck`52ThOoz|fEPKXrASuDxP|MnIYe)fWuh)A4yUj#pJylHtQ8 zaI@@r5W2BjqA-1SH=Irl9!7NSpwSD#D+teC@*IVc z!23@XAjpuVVBx94!BJSC)qx;hY-f!BGl<{OZUN#T4n}Ts4L0Bi%rhKqhsQa=arWk_ zLzaRAMq121JjF2w646F<6ck*{j)eh~X%8CV3mH@A0%~&QoWDxFTN1*{c{Tz(> zeG^OM2n@fv?8U&c=v@k}@{H{WlbCHthz^f7X0pUrJv^)VXm}qW8MmtbG>2l`Z@I_a z${6t##!VH6FMdGoRQ%Q9|1B7Qn2JBR=mXG>LTfXH2})SuiaGqTT;tvXmT@S=VT{;^ ziKrnSE+e@FPK<-V@iZn0hG}iZv?3g7t;Do2kePx$l2)X%6e&YK1iNDF5Af5GrFGe@ca*qf32vgNT7Ptjj=nMjF@i7=dTdacr@Ru_} zd@+Z9IYYvebMQPgc=iLzwGGMzzut{l1D zg3AT|;l%S|?Ud>%wW`;ufrW?H0S16vwVkm_u*8n|g0UMt!QF1?;AaQ+9fB6#ahz?A z0KfL_*lt*8`Ga4j7VTSR!2idAk0%2+9Z&?p=pRlc9TzU~vPJ>^9#@Om!2_HSHG38Q zpwlquA?z-UhqZvAT=aa#OdK(Rx4|Fww(*1;GZYy z;NFt0F|Rb6*(Q?TnYV)b9LXCbZ7|xHS)>QrQ~~M9ay@EznAr;+eL#-#*lPA=3q7WR z`$KS>*=Hp8l4Y31&jOY{81}5sP9IMe?0XO73}5v5mgEm4-}b}UD%jA!x^1VAnRU0d zwVByyJNhiJW6YcEn3JU;Z-kiHkq~rG^+xRta0jr~p$$U=*fS*OliUH)ldTQIu!-Rq z+r4m1MMR*S67dRrm%dMwpT(0UNBm( zV9Yhh-HPNZP5L%z$KPmzt^ZCFjO}xfzU(Bqc{*~iT>RK-l}Ima^5(yIl^4@t&m zp=EKl~Cl5L_ns6}$v2Cy*`_#ybo*4=4oY?S@3#G&N?$usr^S32uU~ z3p63B#uc?BYOE=ns0~pJo)-#ncH_@LxETC$S&Tm$3sf6^$?i?MQlK=TXBdlx=gfet zkmg{9h52>5j*Q|ws zHE5O?%ORFcWFtDwo+Sz+y1<4K#SvX(FB{knwSX9$j6Rxl>7@IK%_eF?bcd}W%kE@( zhpi)ePSZC;FKPOnXq+ayz?{tlGO;@>glHkreHJ6I=06|`;C)HARnzN4UlCR0+e8V( za*n7H-$A-xf&6(*evZg6A=Tm+iTr>}tQNl{uzVFwDX=6-=Tc%`GJs4#J`!uN6KE1y zCJ!Us^Q3FRBP6!;NT5j8n#Tjd+r&Utmdk6B7M7X2@3SUVrNd&)-sZ+Ya1#TRtO;&A zfa+<2jZp~K0tmy+lTdip-pp8IHkdD!CMZKsAQKSmhJxh)vV4&*r+khwkArZ-`A0-^ zHLZeJ{MjckqoQsN(U;AUO891?NtsBK`Im0=I^RV!yA|rD@I6GGS|d&6UlEPYL3)Gl zCyImL?cv>F{x#7uqG|jP(J7)*{tc1mQ)oGze@oPsXa+wjf{y5BpV`5@PNo(6f$^E}9Vo|iyIcwGTm(+jmvkt`xPp5#)JpOZXF z@>h}p-e_MFq>cRvsn}RrQux$`E zSY_L0keRlvAp6>Oft+Cb7UV*ZHg+hhz1_xqTlNO|XFAqETGRKyJ-BK6Ku3x>0aqZ! zI3JW<$UOk0qvlneHx9&-=94@|?Nvl>RsWO8ty-jv+^$yOY#aHUB&k|iwXbSZ)tV}v ze`;&hzAApz%I^I{#p#~nnhKcPBP4H=%(OR^SPxx-v3xvGrA-e1+WDGaaqG zH25xzVhuvjrvu4BZc_OuZCGf1lZ}mO{cZ^MnVeA0l;yv&xf6;l;u(gm@M`#fX1U_2 zSHo@WGDt^zoef=P>QMX>$y+4DB>FrAx5LI7_A&VQf^_%fNLbGA4qlW;Ps+vJFj>^EcWV`Kyo%Vw%k&KEvdLm#Im<5^|m_t&)UkB;VRo- z8ApttE58f=UU4fxR*b`zY8JN^+_TabL6IZ1rc7$ zOf^_W>c`$@mYurRo3rmzF~!2_-F-NFwR&HW3#$(Vsaiy}j%q2@c4|yeZTdxZtgCC) zUjlp8F5RBS5ql=dZ%IDU6@5l@U02D*Hjw+bu3v$>W;gUN>UI{~E5QxdRE@Pz>X&PL z46>{S*5OArrucGpfaHR>QgD04%>{X_2Ig5^tsXU(f{(hQtJg$-)zjM4#PVW3agJE( zYi2`gVq3e{@Tc+XA?*LOo;Ss9hEU_;u$J8Gd0NfG;Q!y~OOKCBD$jds;n2~}d*d$s)i@`{(%u59ELe?)RC$wMSBki17y)2cUMmWB0b0Z*nrUiL}t-bjF*%K|L> zrHr@0y{YiWs<2b|L{gGN4(izm+#i92+b#H4Zu-fi71UvF4AS@ztED6COOGVF$Wdov zeTYigFHLd-JlL;9Xj#bMrIA<&ro&m7pOc<}eeGl-6^j>ZKvZt6W$Dj+SW``nEk!`B zHMOt|WxlMPrf!y(fx2oMVi^Ok()QLg!7>);c}?>yli@B7-%*1SSwFG72{f8$hu0p< zOt?nJYdUP13-qR@laQAHHe1sb$V&iQr0EaP1+w=w!Pn@3R%?p2_J_yDHfl-&T@d?1 zQytJ%V0$$+2VDjBji&aXv$K<$dV9RAfG&hR)HEA(ADI3DoVP%?n1J!4@iBu11 z%zmnjv6QfvJ@>==?gw#00BF4D3D%T7NI+7(t{MA?EKAvy^xS}EY@?>QrnvzbY^SCk zO}_|e&IV8{rR>k9If0q1SW`x`F9NcdgoBe+oJFvM7pTZm!KXiin|1o9u8vkL+|4qZ zRVFHDcy;8k`fj?XSRXfCE^9}muAH{)eWF>cxsL~jU!yd&^$FzpY!zLPvshc7Sl)ph z(bU1G7VpGnz|Y`VyS;px@h)twrk8!5;!m>&no4{McsEu(MOjYv8Nhq6Rhs7b4CV!_ zNvhJ7`Mkn=v5}hA_!RTrY?Y?#KI8c_?3kux-&wpbd#I^_?>yd*RmLB;ATO zo~HJ`@ACnyi>3mgfvlgV5xyVu7uX<8#lGwKVD_@6$v{I`iKaQeoA^*RNz($~ZG0Fj z)%2lnIe(EY()1~Wdx>S#P4EQgKAH_AQlsJ+Hdc|v!>>Q|%PE@R|n>uYS48;xU|h{~;dESLEN_61Ri<*?-!ps%#<8HjTt`$p>qL!1-YDXkj= zx=FC+!7`Lsrhsk|yQX!E{BHBf>^Dsx``rinQ_~g*_c}AhH4CA< zl(KOxa{@nMzVyp;xfSP*wal&w=Z>{3S`*F>>sS>{I6tgo)isp_^oJ)S(=@#vPz02& zX(s5_vzD5cf^I!)t7!1UA5FL}*ug4j!gaw87Dcqf3+MNpEM61N?>kwlCY-~+Wc4)R9R4M1LZoJ(a+XC@ zZpGRyXStfNcFS33P1r+ru|iGQLw2#}G-2wy*@`i;d-kv?nlNX3 z*$hpXv%TycO}I+N>!V zYr<960d`gs*6!ErvL>wEuh}h4*eVCv@0zex4l;ocK0q5`4>`oVG+_@p#DX+o4>`;t zG+_@p%;Geq1@&j&uxgsJgNlIaYAOKT5%z?pA)q_LT4)*%x^LN2n&yG-Th@taJX;kM zEswI^O2=0P#mQrAU?a*WF9+QTHrz>Z@;g@6Sm{oJ?TMhtU`rC zc9xZCN+k+PSGrb2Z)hqa+NSA^3U%dK=HEFdc12n85}%&(XXX#TVPLLbu=kW#*hC^sub;fi<|qPP zKY5MabLtA&FU&jBk+Z?_7ZyW=v2>ExSus&Lr0|lw!EnzV+8wBqyvb&0dfh%s-eQ|I zO|wsszcSWBSWn&hf!b>J$B>2lpl_XIN(zp5WB|EIoM+ky>B-@?lD6!8M9MAEgP`DE@rBrU_7X z8-GL7%-~xc^9_U;T>+%55il-@-v>g@bIO{lZ;Rhlr)V7@^U#u?1FYr?#Q@I9I^FCqMhB96HZoit&%FkYw$(+lU%YQprw`Cv_$&j|jCCd_99e~oCo<>L@xisY|r z`Ygl(G(!>9XB2;5g`=EB@!@pqQNnhG_?n{maZLw90!=ae0sLx+SL&INC{smVmaXVc zNEK6Mz7KvwL>&vQVT$KFpHk!ll)%5BSW4Nj)(b7gJDel*0WrVcAo7D3L0ADv#BKWl!Z*6;au%^Cl`BmAyJ2 znWu8yKD4Q+1|Qy5(ZP_GrkXsXgQ9__&_fE zVG3`t?m$I6U(18Hc#8QIzKW=n9S+|iM)DV4L!HX?NIsls7MmEJVIIk6IB6Xp&F5>v`{^-! zIT73mM`W9e`8G|V5gp90@{q9@=PWkax4=A(S0Cq~zUB!$gQ%1xL=>4P@rjyJBZitM z^KDKVX`ae0;~n8%Gf(416BN~pm};KEi=9-?XY#2|nqi*BS2-!fJcs8`RN-(>U>@)7 zqyqDN?l;My+r}60I!>BzUdTIZ8W3L2m+*d0nqgkb=Q(Mrc^Ti}q!9DFe3z!Ih;@89 zKclI0L^=O}*PX1=!xme?pKwx!c_r_u30wLj{+yFC%pdbNG+_@}&1Y%a>04(0gqJz# z1M?al^g5>S7Tf9jiFqA=Kvd2KMZjGh?~9KJ>z3ZYi-=~i*%6{GO9eo44@VQ!&n2tUThfc{^XE=}5${=AAs_4W+~W@+HsKgzZqy z^EF{j?BZQDVcB={-kPwN@8JV9U5J>)_wtuCU4z>FiqFwxiR2#pc*dJ5J$vLjet-`p zDrG64`; z?(kgapKHRMnj8E}O}JBYgCEd@E4iEes3u&=-Q=eg(cE#%xw3jOYLthICP%&IMhl`Q zd;IFO{3z-f<|4c+zwOlFUAc?4M6Hp(IdyxZ2D{PGsP*!WQ}=V!EjP-He$(TwQ`aqe zrW=ikp6_wbshbwP%#9XDf9!GJsrxW`qZ@6G-r+{&(fi%#aCCp>3U@BL$c=7+?ssRL zRv3<56ccmI;}54UA?B2eOi#v~^LXIUnOXxqbW%RhpHAuyglAUZzj9N5Ab4z6(=Z_J zq|rczlP1Mn_rN1U@L#!UCXmTVi((#ncsS|3M`*<(RN2?va@8Zcb&t@-M`&w|u((nv z2eLTQ^En#hX|X!#OpL#aOeZ3HTRe?R)CVtetR+w5H%(YeaN@@-EYU@dwd8HsG+{0I z7}1)rmVAwBny{AqjE0)9mi&#Dny{8^Mkh^JOM%8%q7pVe_A5&TBWpIMSHeC53N|ii z+7Wxg5^5CBQMwbcEj_}G8E-3k7<M5S3W2Rjg{QX3W+)y!um&g_`i{Pch!t zgjav6u}TwO{i()AO?dTJH@0iStG~LjR})_SHH^bVC6>Dt>sV_TC$$d8f||y8trL}+ zSZf+rwGPLETE=ay3#ioETFZE-bvQEAHcSht9jrJq)HZxI;mArua0^~29a9Hr5QgFm9VHvg)GhZauKFp%IZ}5N~9UbHRV<6 zU`;cU7b{)AO5LpWjpsFu0?P)*SfUd4Nu{CI21d{lv@BuUfEpSrH65tbpEWYlmMYz8 z&^0oq5tXv*l}1<_8*8=hVWs>0Nn=2nN-wDLtJWsQw0Bjw5}zs7rp8Z17deh08OCp# za16;XjQ7y;BFB*^!|>CDBT`5kLZ+9=bssB)||+gM0#RLYumxE0gJcwf^*pj>0ErUO82jl-IPI^K%OH%=0j zur3{^SUVVNDW9e666iV^pKD6$bStKd@s*|`psvOdO>2O<8|O6L1u8JEXlmH`R!mRh z4^3l$dK+_AU>VeXP9LL;XuRdQ`1P`nu~O4Z@wb51X&M{TY2Drst0<&O1vBS}+_Dt`dg*3=)u4Kx~Q8V=zG z8qGD~3aQA*(S$3cBBO(*agdi6jP9D=fV{k5^wl&Qbc2i{O^ZM`$QZ6^Iixq(DAu$V z(i?0{(zF%wIm9T{v>)<0#F(oIe>WUzEYXC&8xA#AXezR9(}d}bGP-KQSVkMYHDN5Hjpr3nEO1N>{VVsu61fOV|;2(h^6>%?GBIFCl_P9;XT(dEQr z9^;(4`-!LA$Xc~O!}o&lU%5|E)gm{-xp9J1hcljwqN`T)bWzQ!32xLJ;)HkUb(|d_ zP8SWTn(8^psT*6h4$v^Sx}I#jMRd`Mbv@abrwQwNvQef9>-u$Lr6#QF*Nt_Wu&$>V zpKHRpo??`1!n&SnT+)PfJ=M6b3F~^QaZeN0H5|+E5fS4E`c1>83G4bz zBTN(4^)#cRCamjeMv^A1>r$hZCamjHqmd@8>*+=Yky?jLH*&NNYyK^xz1HDc<1M4R z)?qu$F#2f1c9>xlX~K4xX}qKf+hL|rtO?s;mN8Kiw!L9XcOeIWBe*t{k0YT9&-jbBRL- zw9*q!PtfV%imc2@xFU0s>BHnrp359M)2GQ_c)shTa-ii-`ZW2NC!8Cg^H~lAFUD&+ zmVDC_Udz{X0SI2bck2G|g!ky3x<5SeopJnE?o+#3sMjVZwWt>DMqNPnnNv3abT0ZZ zI^JuuQ@1&~x*LtI*1(M>Rcqo#GpfPw_ResNtHJN~PWq@?3$HCs+Ey*cjqsO|txg^8 zd%FntwzoNTxVP=1!;s!~r|vwY=OVoC_`<2f`wkajAKc;8VIOqS?P_b}PKVCKQ}Vss zsjFAHo34-79w%8-26^pwqnEwDc9Jcn*z2Ghz3g?^N#QAzyuNXx>0U?NXs*{$CnZ2$ zPB^J1&`BpX0{Y%TKCM!gd7XArpOlYXWO_BFkezYr#>W5b<)UfvH{1xv-LpYq;(OFv{#(raHMq+ju zIviHe@_CC@ zL?x_x>U3{EafV3cGf>Q0gW-_iS73oh|3O|Xol-Y?2Z;|g4M^Pq^r@!e)C1lX#1>7{ zQjY@dBD!eB`N1x}*1AQhr@igsIMI0aY3k43!2%wat6@J?lwTVjL ztbV^HQ{_4Edn&*d>bvoHQ`tnBPwaau`Wg=Yr^?9R@Byn^KGnXtO@7a zilVtDoNp_NHbmuCoNp_MPMUDOtt6Ham9UGccfBi%BPtxn`7d5%ug6@MumhF2PZc3I zD*7YU;*%hbY*u8g9^g||+}omPOK_A=vY4?I>7o^9*c35e6V9+H;(em=EV_ECPpa5S zRL*gpt}d!?qi`JO%^D(86V98pL~o)Jwk)}xPaWaE9W6^)t?D^GX(CipQ=kT-A`!;9 z(zB7MNpun7{KK=cXr}1`(32vc2zKbIcl1dYo2l%jEa&OmfTm)Xrg1>cL=&osQuaAe zhN!hcrJmR|H=wy_qNz{Um6bBZAWcg_*Fuccbf)VUm9oT#nj*X92DB8rHFfEByizN1 zU(;;RwHD7&&eZ*TwwO;e3$EL#KH1`olNR|rC49cXyug#UF&li^iYQI}f!d2yO~ZgX zi6)xzfu0t5nz{pZ7dI zhHL6sqq^^V;(elvR$LE$AXaI@_236$qb6Jrt`OTb;d*d|*hi$s-Ib!wmzWo%CSEH= zhLeiehoX&>p7i}l^mfuIk5yuzlUn$$78i&va$H%h5p~KjPNc40>qK)W_3_#uIuea% zJSEq6v*_)l?!H^aJfafNJ@30itkmIf4YpHM*`?yNro8M`F48pN8f=$1?4*~y_K5SE za1FLs+;-A*udhVq-71#wl(}B}MLSKn20JLaYr-|yVezacT!S4ELls$Z4SiIMBr36p zN-z2z72~uHSJcPERIR&KvBdY7n5A{NzCJD%Xu|dNaq*reTwk9MA8W$(^$D>-6Rxkn z6WcW5`uaPuM-#5EPl`jDaD9DJe5VQ5il@XmO}JJ(C9Y_~wfFbpS53I~{$4!Lglq2~ zgxo{5WW}}j55h+iuDwr-3Yu{3eOg2jjkip!5$kp79Db+}4DC-zeREM*P5FOEAWI+0HG*7KskNkgsYMUf&lx@IA}AjUd%NK1$= zT5&CWL42SI*TNUX8cnzs{!x6U3D?3uik+HpEqqbz(}Zi`i{e{NxE8)7zSo3n;Y;G8 zCR_{uBs})28pO5mPr_dlu7xj)5KXuizAR!j;ad1-k*EpR!as|ens6EdUlpx2;ad2r$k&8x;cKF+CR__&6VGVEweTtce|;X3(-cvBOulW&MQnsA+bQ!LVi>*Skaxh7mE-x8}e;X3)2*rW;9$-jy( zG~qh=SFw+1mSt?sFMV%|kzZkbs$TG$82boKQDniL=ikH(O}O*?n|MbP?mXWS%QWH6 z^BwV#Cfs?xD?ZhPJI{B;R!z9`d{6Asggejo#6eBC^L$?%*MvLI_r+OFxbytGxU30x zo_`m&G~v$kAL4gSxbysn5c{ZnbXV{|cxl4Bf(If<6Ye}e6cL(m=lP+C(}X+Ee~N0F zaOe3?QCAc0JpU!0(1bhBe~A{FaOauHr!?WtGn1V(;l3%C1)6Z*l*?x|;m)%m2Wi5c zXG6ZCi1t*4#PZ;8(C^kf>gyzW;!`?w^u(u&@L4#MQ-{yOxd_KBvr~s-mW%Kz_HgR( zD)x}Cy5+?p7dfejS>!6BiyU)im47Ir=Q!b{*!`I6i&h*>J*BrM%$b)A(u6tll98G) zXWlYS6XwiYrf9;P`N+DOFlRpUNuu$VRW(og`pOoXKCgKOC|42G;2B>(*@LK@Ed6C) zr>>Cs%U6h08T{p|is;!_o1Cl(^J0^4X~NkeK+e;I9 zKi7n12$JPQ>T0YYuPCCvTS5M+3HxpZ`9KpsA#9iO0M_n!3qB!imp+>CY1d#`K@&d9 z7%ZbSU8{M;H$=v3`lIGepj1uPT5Dvetfwik)?lC}idbZ=d%j_Ejw0%j;c|tO;5l5m zn@H7Qgq(N?bB0euTKpnq#1TakY8~~BmPJJBInEgQk|wOd7+I_dYcN($)Pyw{D@!$D z52+~M)`YE6Q7+MhwOdJkpb2ZYl59YEDP{dze;8j`W@*~rdCQ0`K{7f+S)_?66FP=x7ey$QGQir!M9lUi+rv< z(JxsRY5J^Is$Ys6rO3LgR&BpjIa%wh!KpxVG##wf$gjG5Pg_1?Z{}B1uGQ4m?rW+k zztEH(oak3e9@63F+FSe8kykb0Gx>GpeNFf6?fvS?RdX{87`0+VA=`mvc_2SSHral`Z5tBGpDM1*ve_OfJ zNumDv@`$Dxb=L9ra@$EvVFvrKPLzKKnR`mn#yZvfJIf84cGjuy-&J<{Ug^HB)6Bnz z>~~txNznC_@{FQOb#nZlku^0vsFUyCS9a3mSvSZ3S^0vdpt@cC`^(#BRk*0Sz5Sn; z7tSdfTc^nX1v%xsqH1+V`45#r7Zf$BJIVhg`IDyXx~2Z`L6nP1*R}53{v+f_B3Luj zUFttlPS^Bq-Q_@YHJz`!&VQ6#MWotclw_>Ykr+$>AvaiX2P zRlSq`C9=gOvg8=e}e3!sSqqD$_tu?15K7=ucD>8o1Y>- zCBo-8Z~9M>r=0Y_{|yPR)4;!3thAnoZJO+)X$?@RoU3Uk&~*8krf=#UGruLjAyTEC zN#zr?mh!bZsGOgx7i7Z|(C~!Wa(=g7s144J)+Ev@+u(~4L>P;&4Zanib?53O+2CAa zO?T_nu))E`nnYS-8ytj9q{1z8>drw8;yG%L^fGMAorK{&lqa3J9%K7RdjEp9@cw4n zc-zNv0MU5%RN7SADtU&el=V!TZ(A*6uA^ls8t2I+acR&-REgZ0XyUv zO}o-+29(P(H_P4fMk2;}mTzhHFkrXLsHzCxjM^=;HGSE1Jy1vz>8v8d=Dl0SDB|@q z3fXR%ps6=eKW(`%BNi-&5n-+eLo73hO4u#1+#?_8aG3fYnUU;DeUHr6gsJb5m8-c@ z-y@S1QR;hSZB3Z^9@#@%V(NS303wz89{D;Eq~5%c?UkO@F-}#Vdu4zkHb3(~&|Vpl z;nMAsl@+m$t(M7s^0u39zkHx|AGB&E_sdPKT;UGLy^3JgPW3w=JGFJ`zLo`w*zBCL zu&-roCztM^tgDEnwJ8fbC_8m_=?=*PMQlTxUEzo1g94ZCu=Fk@V%H(uVJQ{SO6MDy zsCD(8DhvBY_U+{gcSMd<#QK2lh+Ls*6wtRa=oy#gQ5m5KzR#DZ>*>O2Z5w-1cIZYF`?QuC> zTVmTDmvf0!+a8yunXbH?kUol7mv;C03E6j+OZS~DQpDbB*Vy)*TszyPJ1I9SVuwL@ zQXbUw3(zS!{B4)z_p(?KOV4j?`(7TW=Qveg`azyi#JaZc5c7lFMZc&h-D!DD5qqLb z*NUg**KWEqGGrB{z{Y^?jJ)fnJ1hUv;oj>K=Y3X=S?$WpIXOWQJJ)4*#dGq4o9=?V zs&$@E@2+@3w*15u?xM_7#Oi|XqI|I4rTa-r+Fc&cY+aXC`bm!4?$TYBQx!oOc2~SC z_qge<$U|C}(7j#U6*8vk8e#q#&CcPP|kCFC!@=?9w68T&uAEmuTZZ9aQ!5()jn}6z2sD+bHNd{0|1(B@M0{x$J zlPZQV(pDsy1k!-Bz0lHKy8FAk-EAIsE6eH-CwwIXq-0IqQc?bG-27D@+~ZNLuOy!5 zz*#qt2A%C7nDWP3HCS)(7ff9X$_Gz%5acf(@poA|u84naZ_?Mx{)U+D%1lf}xx2PR zAJuaLKx?p-fc>%iHR)Gp(w72c%S9{0f>qAb-_ z^Urc7S>l!TsLcYm7~FfN8WWUM>8>G5cmFNmV=(1|Zq8iNaTU0aJQ$B7b@%+Zr@NEl z#Bop1=^c*I&o#0=dS#uWbpMmy^6xE`_D72C8s*_Ox$l$v&wp^Mbd`;X`njuDKblYX z9ICW@$X@k-JU4{1P`VbvK?+v+Z(6|;!ACMo%VDWf#IOdOJcyxcQYe=XrxQt(mb3HO z7*@%}Ip}uJmAm`DmBUB#PsYWW42K$;UkCLU!N7*}aqC%Y^n+p``BDsGe z_f?RBDIb+9p&~-(&u#*dEQNdz`MA|5g2{6jj@)8dGyCN`ub-f*#^@3#xg}ey1F&p8prP4d&4Z zOX>&GVD`Vc1)QphT6I-oi#vQ&uXgn!$1MNvd<-3%%f{WuVDXTaBYw0|KAfdc-c(Ln zk^3n(OLuJ{_;c2W2&)7aodX}5UX-D)OXL}|IZmxGT1=a6D;;}z|2uOY<{q+9~DaI>)I9ef9|7t zri$U;yC2X0f9|8kOtqF!Zk+Gn%ZhX@{N2Yfq6W|vWT&eM-7v3_PbH_@aWA7{Q2BAW zgFg7^Xp5)_Y#QSA~6_HlmJ1hCP<$vPieh-26d&0Mwg ze}?}Q=n012Z&7X>e}umK`@4_h9`o=1oc-Mg_l>cSxtG`dI#NA$H}yl5h8`at_fg~F z|8!(lp$ zZB$r1AzID9|EqJQx{q^DQSCyg)c<`R)W~_P2j;sYWLeA zjep_qupAAcIDEAN<#CEl?Yt?U9~xs=ydUB02hb{MuphzSalia`8`Qe4cMRo7>l(#y zjpDqe-KfQTXIQuV%?G~GLSbG0|H{Yz3CxwU#5xfy{J-Smp2|PFF}JF`f>olND4!&7 z!?*!bKH^`G{FUXC;5M|jg`3;GCm*YiEu!``&|lS_WB;KIgu;D>e{G|Cl$+MwvNNTq z_C30j`&o)j`M68f>s}%)wxeUD#T^pIJ_+9W3Z`0F^`F06I(miLSHZHVnNI#=D9nSw zR2g0Fe-&!%V>zEeK1wbix03F;!aTz-IMfeSo|TOXHJ9p5wT0u#LVM-20^&5-28vm= zOF6g&+w10YfZSu?DGL1l3QF}m#aj5a!m)NzF{|G!)SjffR6A@+y8A1)x?ff?tNkuj z3MJLpuB7X3owFrfFm+|G?&Z}g_n+MHUC~}?y}P^IDwK)`dz!)8(%7ZyN98K9C)%TQ z)Z3#z@S6}^9~St2iUoe5wBQ#z;Lj8OeBmz?zQkc+k?aNdvc?N68vbJ7uO{0De>>sJ z7-v`m`2Ptw1-S{k%9^qptT}v}q&aXV{Iz5;yfyr_fxldcDHmeNWfkEsl(mC%N4vup zEV_fcJ8J`f!{Bccd=H`(d?Pm${@TFbF!-AU-)vaI27uoH_AdMlgTG1e4TL3Z6!?t- zzfs^f3jAuYmGE1<&A@NIgp!N}nHG=;vWV3nSs&yrnNIGOB=bmiCRs@GS(1ZDzD%-& z5^nE+vrh(s)K%a#H_l=e59|UlL-?*`Ygtv2yx0|N=S?O)t6Gme2VF+8+ z^ccvGn&P|1Tbq6#kPl^l7|@md5oYtg%0HjdMw3x!dTJlV?Kl8nXl984$m=M26wD? zBBfPBOlp2Au!fk|d<}ft0KeB%M&CXvgZKx74}P_&jK1JhMqh0zqc1p>F?>#|4890- z1hn`ar!xBPQyD$YRmSjXiTV`(T8d{a#j}=T*vvkw6&|#i;Ztt=D8+r0;y$w6M_+u} z2Pr1Piw&5{KKkO*KKkO*KKc^WKKc^WK1y*PJ;Ak)QanO29HAIaQK>Ibsjsqg_3Yj) znLTq*P)kVnp6_iq+1eg}^;yW$1=d)7-Y|1)&Ah z4T3p8OQC)RE$6wJ`^}ttXa5*tHDa=_hVg=hL${g>ktmXM5NQV>_f0Dv#vM;>#hQ2gtu^ z7}n>pu$2@8=Rf2?eab6ff7$37+%i0r--UQWxoCqjkR;|XRt{*>6mtGz8*sxpbjcnV zs%h9-is!QNPMg^fHqzrjc&I$o=95sIFKR{9kXFm<5$UoZcX|Z&lS24z%D~*WBjD>P zxr@PPORHedL+s_;O%ZV2|VedPlXCCn6)GaD0f5vax}A4ZuA-uUXU)h~L*XNsP+t2L9vo zdV`#nHz4X1rCS32Z${ymHY@4`giZB3VZ57{>bIP2$y*Noqw+R_+?U5aOQteI#rh zQ|uuATE{=EgZLEi&juS`TfTvPud9J0b8jkpzJYx>-@rbcjrk8)Ef+^OjO|Q)U=YXC zEe4SNP_nn0@Y=DO@J%tR3EwYVEthvZ=3zDAdzOPZo{iBNdU*HP3-A=a-Fp(p_iiU~ zI^jj)n^Tu1zNLFvZs>TMPvZD??Ie!x(O#DLR_r8R9=$NuX2Mmd)r4<{T21&KsMUmT zd|FNTZl~3RZ*f{p_`asqgl}eAO*l$hP58E@)r9X=T21%{rPYM*N?J|W_pBy-|8XSN z0JIvGaV)t@t*M@ei*5x+0vCN!`6{k>b$3k8C+CojMVg^?XBA-yxA7RCyJy&mh#TiuF z^NmUHwaNJger+@SG<|*H6cF46RTx7r|Yb?eV+K%K*V3bb{DxB&vcs5z8EjRgBb zHj;cs3Vil?AC$${Rv-L}*jS1)nQZbY=EbZvcX8*FyCq#UElv34mO}!*5*MFGv}odE8X*b z7IG4skW9HnIaoHLwb=tKd%y#MqsIfWt5%zY2ZH*5z_(@|h-d6wzz0W_2LgM`1Jx^N zRsR4|d?jHI-(wjWQpoVVy+gFhI!m%Ptn2Ing$&=zyGcF}GqfFyIv`7_Eja(S;Jt+U zP*;OxGOb8)Rs3zj+on-@-zRhyzZd+Ra02cZ{!Ca7KITN6%K{T?)4H@ad&Zucc$*}y zpMQy1Z9@4r$(!V}QMrwn!eOowa2KND+%&BK63WW)LEg(E|(JUuwDD$Ia|c&C7A z-G@Bf^W_}-b8ReLKpw2DwpOhVbM&67889osQ}3p8^?t6JEwQ#aKVA5sD(9l7k(5n2 z%piYnvdmCR^uCRXH!^i zoas3-Bwyk;gu7ClU12t70lldd`4Yb{+*M*9=t`+{rBHaM&=Ky!rlyZgvcO(PDYvji za3;2em9b=yE6Kfz+#ATfncUl8f58G@M?=ef;NuHl5~~aH2wMa4INJ^K6nhBr40}yj z;M+oI8NxBn2##T6c$l=n$`j*a z$Z~+O5$sHha2VKQ%s@8QmBa(Y6^v#2BCc6OuXkTzHFyaWPub-m{yhv zbCPYsoaCA?C&S5qB>5MU|5);$Xu=#$F=4vXOj|(CFzxoUusNpvAm^K?CQXOIU1mB4 z@_o}OzZCX5dpkLWtzaL4T*KCb9Kp^frLcKyA-I>alEf6&j9mtw&!ARQSQ488?ppBe z(G=E@ET1Mhg!KpecB~f2)+`WYFV+bpd~YqO5WX;%Y!s7ROmaKPvm`l3Z4Aj+l9f27 z)r8#XB%6^>0l5oF_9CBRa+i>NjeHi7dojsvB)5~?!C#kGE1V(sS(41abUDcwlCdP4 zkW438K(dfzG075=i%2dexsBv@l4nSsCCLQEPg01tOx1&9$lZiw0m(v=y+mtsm5^d` zFCw{^M1jpTNcJ0#Y5FB8hw zNG>J0gJgjjQ!FOAh~zesXO#3n?OBq{f-!Il`oxesmfV%d-GpR1`4o`5kle-OUPN*m z$ulIG6=RDb8EeHjn~*!5+y&$=BzG~nOUV7273*^m`79=%ZRFlg?la^*OYZa5uL2Sh zm?!1g6XO@2=p#I-y~sb7{F{(Fo!kZFE+ls`xl72sh}?_Gy^Y-4$$f_0XUWaHC@n9l zACj>on~+Q=SwOOoWG^qwNil^gA)iI$UQF(7| z$z~)ANcJMx+b0l8QB3X`|jC6O#Ewi4U2Eh#u8MjA_FdtynWXr$OmNSQH&OTlf^5-6o9 za%oy94UkeUfly>1AJD=_DB&X%^COo)fkFvw(n1OC|Gw|u=gb+6ociJU`h0Qp&N^$~ z_g;JLwb$Nf=5@kz!uJTz3qLEoDEzL_%vbLTW5PyZlW?`LMc68A6ZQ!c!mKbSoD`lD zP6^Kor-c`VrdA~i8--267GbNfPnZy9g_FW5;k3}inNOpzMc60I3MYkA!fBzYQ+#2I zuuqs3P70@l(?YXA@r5nIK4DfkDV!2c3(Z2tZxQwh6T+-8C!7?X6HW=w3#Ww_g=Ue; z6}AZbgjwOF@SJc;cwRUyyeKq_nS&>66gCN4gss9pVM3S{=7f{NbHXX%dEvD1qR=c+ z{=!CKldwhDD(n*`gjr!uI4L|QoD!ZFP75yz%~ItrY!o<ZIW>PIyjuUU*UHEo0gy zVXH79%n8p4&kHXKz2%B8Y!xPiIpI0sdErH&SFiZOR$)Sz6P^>E7hV*$HZXodm=m58 zo)=yedMlKtuvM54=7i^jQ^NDYY2ihow~}dd!gIp&!iz%F$WTw%C~Ok82wR1H!h|p< zJSRLayeRaVR6}8_Fd@tebHYjCIpLJ>yl`50QD|1FKEg&}lQ1is6rK}K3C|0sg%^cp zwQ>+P3Y&y2!d79QFd@td&k4^9FABXiYLPH2oD`lDP6^Kor-c`VX01vWHVT`BEy7k| zpD-cJ3Uk6q;W^=X;YFdhPBjs>3KPPd@SN~{>;5*L+jw5|MWI=*ng|<(O~MvotFTX) z5N3rr;iT}Ka7uVyI4!&=G#iw^uu<3~Y!S8!6T+PEobaO1+o%=^TZIW>PBjrmLpr-ai&vz`1#VT-U& zm=#V6r-ai&bEV=7TZDbWDdDux>`)wGi?C0a6;2ALgwsNE7323^#rkK3lfo(Cw9s6w z-VnA3`-EAccWqt#&UH<~$(tB+N;oYvElMkF5%vkQ!b#zja9U_u6<^pQ>=R~%lfo(C zw9xESd|`{QPnZ=>3a5nALer-B!WN6W$>|ejg_FW5;k3}~Q7U1Juuqs3P70@mrb97> zEyApDQaB}?7MfcWQ`jQx6J~{z!YSdj(A=u{!WLnlFe{uCP6?-lX0PH4TZDbWtZ-5| zC7c#E?qmEGVV^K7oD@z8r-f#}au&7-v%*Q?lyF+u*r_~)eZs8JbSVd6i?C0a6;2AL zg{E6Eg)PE9VOBUPoDxn8O^@OWTZDbWtZ-UrZc`j#i*U`WXn~u4@r5nIK4DfkX)(z- zQ^IMXIi^&?7U8te92Z~MBJ2}pg_FW5;k3}4P<&yFuuqs3P70@l(<#O@cM-EEiIc)9 z;k3{UDmP(^uuqs3P70?7Irq(wG={K6*eA>iCxuhOX`vZbd|`{QPnZ=>3a5nALX%c} zVT-U&m=#V6r-ai&Gotvy7Ga+-E1VQg38#hTZp9b22>b3<&j=@lQ%nB!kQ^IMX`3=Pvwg~%#S>dE`N;oYvuT^|ui?C0a6;2ALgwsNkReWKK(3}xR z*dpu`W`&c&DdDuxyiW0jQ^IMXdA<0;7Ga+-E1VQg3(W(HDQpq;3A4gU;goP%Xx_m1 z(?at`r4_aa`-EBHq;N_&Ei`XZd|`{Q@9kCauV#f)!f9dSJIHSlW`&c&X`%Ujg$nzG zQ|}^YTG;r93KeFBlNKk*H|L0r!WLnlFe{uAP753VSosKfGtihd=8^aZ;~$NGGQPU* zopm3t`%&HVb-$=9U$ADuRSR}6IJV&a1!ouh{(=uI`0#?iUhvBW^B1-){L6)(U-MXu>lSsJ)=xe{S)&7XNJVFBdOg zGO*;#lHXeL{E{n|4lVuo(kGXGXX)=Q``2Z!Sl+!nwfy7Dzp?!L%WtgjuOF&^P5t}o z|Ehkf{>l2U*MGbId-X5YS2nC_xUS)*hIGU08-BOp?F|n%JlgPh!`B+V-S7_$|J3kY z!;1}bR*bE9V8we@e164$uDD|5%`5k=ynW@}E8nv69V@@M@~11C8h17xY5cv$bxo~J z$)?jyZ)*BT)5WGAHoef~t*Tr#Z`JZuH?F#O)q|@ZTlEjCURYd^5|V{1RP_A6`uZEe-M#p~9rn^<>l z-LvbLZ`iis*oHsYFuCCa8$Pn((;L3D;inrKH*VZ`?Z%FcT^nD$aeU)@H!j`uhD{G{ z`oyM1SFF5Z>lIgDap;P}SG@L$QjEhKGv8F3S~JhonMJsHx!7z1UT>D;W@SBYRyN>P zP4d!ofSM!_ZCiC~m_1nnxM`oA#1#&L;cAE-sk6G+>nC0FrIE%Oy_fz(o zwYa;v33oTQcn8f6?+$Y{?rdIzJDS(wPUb7T*O(h{5A!An(V@BgdZ5E|{}p)G+@AyQ zo%<``*||PKe^;S@Bz#o(Vd1BRUl2YeydeCM@E5|h)y(--^N4-IvvZgE#@sfaoL=FH z`76Q6h_+?fQvR)uab6VOrQGH$Ajg(CU$m{mQqj?J*NC%4Xxn95WLshDZ}YiS>uif` z{RkLZut#|3;tQaUE}jP7viMn`?URNwa@H(i z4qJuwG13+-$A%WixpL_ZrL(1dY5sSXUp2>=A1uES_?+ZVr!TbtT}yPG+LoeV*UI`ux`h z^2;`oQ?rruqK&1M#;g!+`(eF8Unblp{*(WdElQy5|jIgxrZJYKTn^=cG z6Mk@0GwSdO(O=rM6ZF?Nv9=e*vAu2EyFRuXp+6A+g-!cF|4-y;M}lZJw=mVaxBNY5E8$l19~Iw@ zzLmF6Y+(<7cFQzker26E_t$OX?xr%N-O|K*7WdmPw$vju7^!POpPl;(;M{HZRby6e zdjM$LXl35E)XL=L^v|!?C$`naJ(Jqb8bCuU8tX0y_JDgLW#zh7gFMcXIQ zm{HwjwX4;K50?7#j5%^8r6?NT=3rCZviJjt^G7>A4D4C_N#HGuKMRa%Z~vN4&c_@q zJrBHP@rpRax1BPxy`5tbr7OCA3WnuxzJYNL^&VJfOrG!KeS;Wmh)SSus_-s{XXXNZ zSQKTTYlQO=%ZGhItVJxmfg)UhSU#+dYH$`I+&2q_ixJC%4MJRoa36155SJs|gH5s! zbOY=Z4|d67&?^z{!8ReTLM-1j30EVQ2P>1f4zYZ*R(Ku4ebZ-FgP#EU<|sluoZGJj zeax%}eH`eU6J{gm6cF2La|P&=Kp*dcYz93fOv4)T&9LwRvkm+=2;T(D$Tx2UdgeD_ z9r@&xdWWXfWG-la|HBF% z-+Sh>!Y54{{LcyTU7Fy39_ZsnOa}B9fxh_$-qZ1M7v>c3n`Q#|Q{49O@z&7&z~{|t z5%UG1=jFgLK+nXy*MathbG!$@DFgbjS>Fh{0_dAc@6DjAgw@_#z?logn{nP*&^5yO z-fx3b3-odO=0VU4f%twQ@Ap727B2N30%r*j-=OHd1N1WCI`5s}tQT(d-Ua>!;U@24 z@UH;+=4IZyL2m~7u#L}wZU*9e1HAWuz7godR(=F@3lMJSiPN4>|u`GD|4-iN{eAkZ^^iJx)v&11q3dmjVmuYed|-1Niv^1h$> zIBun2e1)I%J_XJvfEZct)1aRa{3tFS zzr4Q%e%|{sLci#J1@sq$f8%`>oWB)*+4~y!Ujlmg#?-Hao)-SX`v&O$@V*KBrS~o1 zi{7_^zw*9=nExp>{zY*9%ex4U?|&DxCye>u1E&P&n^ONDLC*o=+oJp*f-V&!|5ZSItB;RsaOO_otNl7~dW8vpA^3g5qds2AF#SM$ z_oI)OF-#H&z3MLqeO!2#-vCZZc+y`9{-AK!ZvuY^=-~$0YS3xn-9E00no;4nzaIQC z;XOVs5t>uNd;KfGp8$IJ?d;8PHyv4r(^jm?@-u_LXe+vlh?Y9Dd$8Q5Z=(mIayTZ5m zyTSQA;X{50_-_}!)4vt`-v@f;UH(4Me<1urzZ0B?f%q0v{~++)eit~C!aw$Vz&Qtm z#`a$c`aQx&{M*6#Qy?_9e+TII0`U!s{t?iBF8m9>7o7J4F{Awi=tqSg^!vg25D+uk zPlEnSpl?3n9|!$WAin9&Pl5h8&^M3!CqaJ#=$lXaL!h4k`uL^XH0Zwu`uO$RyFpI@ zeY}^L0e;RO2j@xQ7yVPvTjY5$Gjd6fAHT7`l9f={#(F#7KnG%{j;FIFZ_Z3+u;18@Q40` zp#R|LOZ(2qR~PE1%DdpGzc!a1>X z;Fk$2V($UJ9EkNI_6X=o;oR7tfm02{dJ%gca9-^F!1=L9!LJq8#Xbm59Ei0e_88~| z!bPzUgR>ZjwIlWs&`W_>J7OOLy&ULcC;m9-1|YtvBlbzqTZCIg7YL0t5WO*(4PlFs$>5S`isK9jr{_g zzX5vY%duaA{*v&2$9@IQSA<`U{TKL83I8tU!D;n1pl_az#Xx@@=$ro&D+T=x;WuMt z;5;Mz`&b3|-x7X1Rt5eApoib8s|JlYKiDLDTOguN774*EHuk6$`#0R1n*=VL3u`BxymHzU>r`UT;?$5w;$ zbK!r))`I^F;V)zB!G95ml{dB#^nU`e=Ekl7ZAyrK$!2goVQIj0FWClu84x>; zk}E-12&+o20%tA|v!>)4(6vC!my+v1*8wqKN?rkaArN*~$qk?v3zwGM1kMuSa=e|5 z?_exxL+DDNZyHP5K{p9km+S^-m2gc-2l#7+8%k~kf4y*H3D#b-3FwiKQ9>qezYVFe7xjt;HOJ6z|WM7122}G z0zO+Z0i08MAF!RXbI|-Rg!T<*}4boK2rDBbx+p)L*1|H%!2rWrUjc9 z+_d1}g2M}X7u>Vp=>_{1_AI=A;RB1#F8au#fyKGSk1qc3;*T%+!jh+!d~-?t()CLZ zFWtMWd)d&k`r&mSGTR+yZX@T zSFJv}`owCpX5pGmYi?Szdrjw>!)u;c^SL!YUi18#+O>(bskP&4&#wK_+V8LZ=e5ao z_pE#Ex_7R-VSUH?;q||@{)6kEUVmZz%^TjZ;cXi)Z2aNIf7$r+jb)pvH+^l>bDLg$ z#fd9MuPDhH>}@gM!vEHTf@2~4&ol3Ve|0ABFJ|Gr9$wd(@m{gCm{)fzd7H48z7ppK zw_s0tyE$xLg}+zBGti5_K6nKZ7_X!F>&M=H03(;g-!c3h$Nv5V{!;k63xC{)a~D2@ zefKc(OXH8<4{`lNr;#(UWD-{U?Xas19XHvFLb>~fzy?(<=N&Nq*_&kwuL zkGRjTy3en<&#$}BZ@ABIy3cR9&u_cW@3_yOy3e1v&wq8FFSyTtcb~s-pTE?nF<&mX z_5KPzuQP9q_vmji-YH#N_k#Ji1y$auh4Z}kFKqShThwFjTl9i?`=Z}O*l}-hU6nVq zxXSy@#rJ`Jw|8nukNFIK(e5)#KIUCq@^$a%((BBrW!U*IgXOhsz5m^1J?6X1mVtgb z=r;ecA_aVRTIg3{P z;ha-Ts=T>ts=OxrUA<<#|Hk;5*r_Fz{;4HzC_T00xA51BxXWTI)-Azbm3L%)kIAlY z^C#C=d7oVmiyQv32Kc@jC?du*?@JGi4<>Ikhmx7Gt`mvTku3v*gQlZ(eC$MWcr4YQ z7)y`l1I?bXv5}pLOsc;y!v3+rp+Zh4AGa0q@?{k8Ge(iO7cd>KXEb$iJUKdXATgR4 zN{%H*XNyE$dNg%!Vl0&&K9szB9BtW?ObpD7-Ig94O!hNU`{}Xda0Wys-?l9US!cGW zQd=T1#fUt2jg6*;k4G5Ysi9=#@s-J=2NJ1B@6B3*Q8d>&_3wdnW-M%PF{gWCBx!pm zjI<{)JTQp5Saw(H_;6xud^EW)iGCTF!R#JQCdP&^wwB+WP7k^P$Y+cysn{t;y}Numw;z_#=-8>|6sAMQ^>JVp16r3O=D6QU1x zMSAd1^4P56s;WeaLW?6$H>U=ZVbe?pC#=Pr6aARWwj4uI?HnItgOVz_EuB7@vLtg5 z&(0x{Gja?%L}B5B9dcJr-!{|1#N6;=LIw)6$y`mM53WNxx&n!fPUJi@lb6dp(`bA#A+3sdc^5nkc(9z`RzQoAhG_|a0OZ1;eqVv*&_wWf~wktW9JWkmP zqnfV7vE;6l)Nf*RqHjC8{_gSAXmtAD2GuYiEp8l{G((yG^ynbwP1i(bEIDLc+uMi7 zha785e$HgJ>`o42!1_(c-c)9cGMEqK6O$!J6GsP=c(OT0lSd<%P>rxM<4LKB;v`$T zMw0zjrwtempCac=#a$SesH4*q$b+k4m?gTx(Yq#w6GLc(`*cn2DCoUglM^b5OAI=5 z-}oR`>&#f#^WBJHx)sMn)Ns=Dj%SjiC;-$*B9l3l9vv`Ss2hUfp=QxVt6r^ac8bjj5(865HG)I6-3Rm8CwIya1rD{WD1F-xeY>iEQQIyJi`a3!~+eFAV9S0 zk{BF3n&>~-GdgH15_x8LS2Dx6POUN9LXPr~uI&kiSM4ce{7`vO=!Zo zb*EWkcH_z3-kskYfLbyA`QoS6`e4J%`)~eXocxbM8unOBr5Jvx;GIORHs}s`BlZV4iA{_ z(TP{4#!gV{+-kbh(NHaaSb8ui+OcSI9vn&xA5S8hEN;6%u;ti!C1J)h#LY!p+RdZs zp#p|mGtedDurnsMw2e-TjHQo{CPq%c*h^$iv<@D})EYZ6q$k!aQ1so&(_>o>C6A8} zCPv#&k6;=Hd!pmX)14#SDPeEmK07k|#|H;HM|Tb;hEJOIyT`FIbQ~W}k0#q_S6N2u z@C4fiGg{^3$&TTB5-|OT$J($^VQ*r(vA;A>cGeUowJS-Z7*xu%W{BNsT5MPEaGe4* zv2$W9nK1{FP$9!(E+u3wlZP?tv;Ek-@Uv$)b=roeLy{wIdsph3 ztGywQ%ej=Xh-O78lK5r@7IAHMO2?dNQ-`^Q4?)O*1jd9#TjQMrG=^>3kSal*dkmsP zLLn)Tld*8^i#}rsM^`YtX%5OPs;EL(f!RZBQN>}Aa*6_jvJ45ejfAUoB%!&7J>A=j zcvS3+qz%Pvivi@LbF^S*oH2Wb68-R5V8<|+NDWh%&7n*}oc2tAVk9|WdWMsZY8@Oo zk=RdbfQD7-cxue-O`pOF-7^fiPmbQh*dy4p8BEB5^pNQtE%@ABM4xwyYioAT^ke`2I zSiVGt<)0W9EC2;2l%|m_9_}tXqa%+@$MvrDINGFy`6q_K8{%97EHD4mtm+m?e{)#d z;-Ijy#X&*MX93M*O^WV<=6W`1qPM$Q_cZhcg5g+(H9VJ1C&1}}7nI+B|si<6=J&XaWzQ}w9=kN>`tm1t0(NRUC+Z<`??BO$dwJ3)f zC78ktwV4cUbq*D_k;{!GFQcI8+l{0z>J0 zlCAJSBWAc6hmJ*r-ASzY+Pzcf20Qu4wl$w~W=jx^jXqog(S&V-$pm~9ST?a{WI&8e zbf;axR#BwKp$1s}jts2XfzIK<3DYq=0E_4tKA|YWdRlFv<_c_kU0d6fPb80U-%Z0X z+MR1Xdpwk$++sjV5cYDKPRF z%{8BjKFd{-R~#^gYH1eW$#l10-L4VO{7sV93E%#(Z2@O$6@WDb;i)sFE|mS%xneRobM z!r@Rp7#2RbQ0K)&h_#+*EOaH0yLw8I>`V_>uOeNJW_NqHIndb!=;=1Q+V{41x0^lf zt-DO;f$omZ{axljYj@io(~(JEd-YbhPa)(3-J_`ySRKPj^e3JE*yx+~(NWA&t}z4f zGn>|>MOVt3m0jhj9ZSF`mLYo4Q=P>>;NUE@dl2jQ;jJa#B?Dsb?ka@aR(-^1z8 zrNK_)v2-i_|8OCa8C4Y2dF2bz48KILQvQ+*fq$J|kJ4@o~cwVIp2UFb7PH$?N` zIQ&;GmQ|9JKt{!3#3;^HMDI(C!400lwiSMb{=}fR#og&Ph?1rEB~B(eKJck(>!Ao8 z8SOemW6_ILk87Z-UqQfu(d4nzX%2>!Qf;fTwr2P!wL9Q+nH6%oL)@DjKJIpzZVTo( z$1y9MEKsL9vbi8qkrr&W(Tey5sf^3ZDj^18$;I?xi8Fap=Q@L$5ijC;R-DK)^Pz@G zL%}dCpvk`(XT9lDhmr$0Vd%$Bh2b-KFXcJea`>vP*R^47fE$;tn2edh$Xgq>Ju=b@ z5~#YxY88bp^G*uXvYhA0K5*~usPTZ{gt5HVOg_9d zvm5hYdD#M(x3a}?78dOT7;b1ide4*!AB@m}iovixZOti5vGtb1;vODn1adM{9<1$N zFop$#5e!6R5bOX1oj*$tve#@4dT~OZ+zB;%QXaCM)Gas&GreP0gzX*xEz$X(-DpAS z@~CDo>^OEnAyaeA70eO0QL&Nhm#tAaAv+Wb)rdtBYEJ9FRsG@4ugf|nIHz1cg+bxy zJI#u^LLmo=))pK*g^Aiv!!bDqAEDb>LX|0|?aWp=L}`W(A4?sFUr=EY5$laE>9i7# zV@RRWBV*t=!63LtNx!4*C{Y;lR4|wlk^HRUV~`W7$}2I+fx^1(PLAocZ6q-|#?>G? zj|##tIc-V`a6uBR7drNcFtNgnVy8u)D=eB`EKl<0%q-km8$spmQ&3-PBSd-zD+MZ< zq|m54BrA3S#-2w{ks6E+sakGH3kEW%>MT;J>4@1F2qYJ*E*`zxyEkrV(e@xO_CrKs zFfqdVshF9voEM9TM99Aa@hn<?3mcYWrr8t5_V-|MdLQ))|SZfr=iK>y}P&b;z z0r{aU4s(NE91zh3mkf-EY;hc@tYW5gSP{E$BH}3!MUav>eA+2@9P^6$M7se_vhaZ+ zuFhI#0$StD=tZRlE|8*tAStuNRz$lTJE1Kd;q!bU62wP_?!wic1kS@56wuCvJZom>1sxaZmg2^TZ4Ii& zcDaTW)`qT$d||!)cKEdBMz8q=TcBVJizKQ!U!O~bMMkGMN>JljLh?gZ9BA8A%#Swm z5}{$Mi^4fD@bq)}J~5gecHTF2JdV{kMwbp{T6(GBYH=5a8NZOjI6Tb_b`t?jzVk}t zS37L0Wi(oo(mhzW9S1cUx*L{%^jSNEkWmn-pi8%+u)ab4itEN27hb7T_sn21R^b&s z_DLa!aUv&61!pVno(vN~p6#U>#&=6x#8q3!api`t0M!k}<{69u?@DrL1lwX*Y+RrD zsr4G4?zS1Ia6lOBELl)?jVBL-88{P}Yv=IJO6r3`{ab2yPx9?(f@y3!Kp%Cmtv$R`g)?@Y++LQKA=^ zLmqUdE^%?S2=3UjKv%f+?P9+ksZhw%Sm5f(hz{^=9GqNvj+dVr zjuDv`uCsz0oxO10@J>GVciMcrc}zJ#Lq@rv*!462)SCz>Zx4W;XZm(Uu!Nx&p&z zmp|_d+S^v{7_LxzAr*8TUQsxXsprn8E)gU1-^LiZ^lJ{x{w3amcH&=4L_wbX?sUN;4pnh!9WHVh_Ms1UXYzPz*oCwY4>-zcnfz-Vc}7NWcu?nL zbUO@Jz4^)q1#5ru6fQ-KC3vZguY(|Y#$M>tQ67A97-qx^Z4@yu^#cYB1>CwDn+Q(+ z=m$kGKX6H6V37CjdI$1n`mLkK?Kyi#W@mEjR1()nJ9xsE8gK_%{W^0oZiO}D8TYos zNO0r*9$oP4kGvcZ(AeJdMS%YN{b@6%JO4r#3PUNl+aJAQoQPZ@j?gX<-mcCXId5s3Dm#kyf6>wGbREaucX$9*!syZ4VTQQ~9>ZQi zt04(_MGz~ze@Z5%H4l=>)t#U=8bPByMgdU<^#4;lceN z6ZRS!fVZIR63CV9bU40T2!kOeJsMcCu8L+1ZO7oEMF}&;mne}bwyXw+Sn?E}9!U4& z4e(K3Bni10Gsue~BM?$G9LAXIun{_i;D=^cA00n-45LW>nH*I-OIpP#3nXylD>OL$ z#!VwMev4*zdIT!ro)q>Q22RiXz!apm8D@@}qq;(nK6VVs5go-VOZ{vz4|Y?!72Nyp(cqr$_WD9!f67jx{EIgqJ4aIkaV~LVcX%> zVzKQ&WyYn?AUe2miCmzNGWNoD#w3QV36OAuij@xLDJHyoEii*J@#e5COQIA`8$AuX zBXB*0socwicx`GBOA^v^(uFGnCa=`K=1=for^66D^FxW#{OiKCXEUSwZnGP7N?*5B zz|A~Er$WwmU~49W$`4L-r^fKoayZA)^S7lkDcmB=^LCG?2J%nA*;mHJ>rUsxf=nY$ zz~aC*w-48Cx7mWB1BWMy1F&ok;GTAI0BCKdO3c=9cdad-rfo0YMaFF| zzO#|%22FB(S{!gQ1hpv84alxk0`H4t;3ULbv&p05$B*+KL_QD8!#MHYG0%i4_Uad1 zbr+S%M?Yk>C!- z-Fq`MvS4B0Zen<2!P;7k=ll!#pbX6QF^Y1YWm{}DX%L|dCldeOyGtc4%ajGU8V7(8LN`I)4D1Z-V-#hgz1D=jIri$)54pdP`()o z6_0j6!tiySfmMRn$6!81x@7mPFCMaUj^e9hE=wrzKH{Zw>A$=@?7c}CBRG_Iw+Xw` zybX#AeB46G)Pq>y9um5Ac;LnXi0-WKF9)wbNAEv3ci%YU3Uu?0+k1Q6rYw-m{8l4; zhdRszmL@Zy0J`ncY^j1P*NBaG%4n8Ybdx_aI9r0jX})n=Z!b(g_`I5L9PI5)*~@X= zC$L-(bl|qAUipr`pdGDKL4}%cyb|eUMTewmPThD_Z|^o_eob%hDZCN49pq3iZh_!V z&EUk9vlZa>UeSWs_{(f~5Y4Kx`M$Mjwc7g z{=hxZuJMr(97HAuB4QkU#gMXbHDsfieZkgWW14XT4kj8OFqtFm#{>;JCXpwPs%YH7 zhY=0+f~C?rCh`&@L*5Fi+x@zkDPJC645al=C5VeZxB+m&?NK{N+i~cCm(sD5HkP!S zlEdHM%LDh3!Nf!x?|PyI?Rv!!ZxmWp-S6(OVhJ~`$B&QN?-!s@h6*9Lo84ing(dQy z6m1vlQrQK=->K=~wXg__ho*YBxZq_%7JVhHNa*9sStG8VJ&PU40^bC4Sy^Df4$#wc zkoz!OU#G5lbE2b2nA1ipr5IN7n0 zfu+Dc>K|htVTHb&LAr9*#FuFW>@dy$-CJ~axP~t;A|&Q=^1BA#OXem^=P2$ZCkE9u zU9eX$jO?X7u&mfe=wUv#9>v#jVE$>BzGq)+Ti2e}ZFH$(BUL{$Ff++wxR&NskF!Ut(>5<0%}mol1%yG_iucQgj}In0@ueWToo^IO#gbt-MuX91 z%8PMTu{N+qNL~Xm-8B#>yA25o?&0-=@G1WV9@gy77-unZ+u?R*yK&nQPkg(=aon1N zgN|Tz0J$aDE6E1cH9fqg0U3tbh1Dx`fVu378vv<+V~o{?Vsq5i%ac|+oNb9=yLm+s z&}-Zm;e`l|w0oS;ZtCXLXa?_k1YOOZ?ZEX|?e7%<=_8Mbr$raKA|DXgOd04IcbLF@ zC?w7DbJ8|pTdrmz?SSZ-q}vaLt4+1m-5n^K8K-K+;#GH=fAy%)-^=1p}HHd1buR!hgU(cVdAR=(9y^8A_(ELiYpY) zOtF+)1qT~@Fp!WP_<}J%+lK_HWIt=70l zDi@517Gp+&LI`tq&o5O?bm?xqQx|;=iPC^cIve{Myvf9CPOb0|XE0~1(1snap6h^4 zgDJ1KIKr>z5pO4CZl-PEZ0=z1WnXn-4f@e|E^A$U>Axr$7FIjQDZaa~e%TkTm=M!* zW+B(v*?DbmFFerrs)K8-`%BfmWInT~u5Fm`vvo`V>})J-v&BAodAj1*?5T0ue>v;o zwynk8unk><3Weg3@9b?bpLH0pH!%S>Xc)uTXU%h|ESQq^Mw(S%hj_?@ES)Ka7i3`9 zSVevuve??y*3qF;SZ5VV(LPN0g(j_$JW~ z*{!gEBjwuWAq%_8;XD|#9A`sPd~6QYFfL_ur>(6WDoFJrj%e&wI8d89hR%c;Sk1XF zHEi8s_(Bi$(LTK+A90i8+XF6l|f_Gig`>GTe1C!vJ7TGdKzA}+= zM~3-~BRrCwqm)P-O}bZ2?7sN`mP#zX$D#DO#6;2rOtP?JbY`k`kju~S`ZuU~q`Sku zZyThSskm#<+d-V5J{r9pQf;^n<1Dni-;O@feyFNZTsXtt&H5hQm9TN>9oQ!Q1uAdIw<{WetT?O{`F0RvHceriqR@z9ZVfSS=SmdpKpurE-mKws9yCCC3?nOBi?26>; za|{kb)ay>CM!xokZpB$%l2Kc)z073?>-kIM;uhln);o()c!^vRmsuCApf8cjWiG?p zF)>~u7aX)<2<-hbk<{xVw1xJ>8rb|)ya=5d)KyWNS& zta)6fz+UNuWY#<`Q(UjyCb7XhAI6NQ$A^+-=Rb^zz+Moy;~0)rcyVC>iq3rpgtdjN z*1+KquDc~i_nB?@G<7=>imObxSl0+1!^~n_vcrA40sIXsWdaukGR9P= z5!dG2Ys|{%6LUC@*eq#Wsm;98_%)kI{OV5p-i%G%Xv|WUz#nO@$*auEP$OFl z%Vix`;YX&6d5F0^I zsf!g?uln4o&w&|gj%t)6!tqUjg2XP5=5~+j%{--S8=_(TQg?%xb?nuX#uS9wl$0h) z;;1njqiNY6a9O#0d!Z~6Xw3lR7VTMCsAz-UqcUb)XNHe}&%AJn0_C8Eiwo1^w!V~- zi9zvJ-Gj@r0psHs|~ znvUQnzfHwDsKPNv4O*&ton}?qKGm+nPnBN{4Ra;t?zM~=;cNpBoKnUyG3Gan{^ndY zRqR)6$k7^8K{=pyFjdqEtOxp`I;uHL*@WVl>Z9nTdo*eol?pqLkP@10$mK<4jk#H2 z`|}ub9Yl+$3DSs1$z%KsMh&sbs3ndg_7LJwzD*eyT5zgI)YBQ{i$x42QDZ9l$@8iC(6zOR1hVKP*hHoBq7vml?&d_IU5NmbDq&kxgTn5HL&~u4`d=mv}I6A?IShFw~5t?dtL?}zah$JuuLB4h^aPm}5naz(ojk&yR z+Lck`UXcv)h1^6_qzY0{mR-FnQbCF`>I(LhHA7uZVTMNYp`Of_oX+Qic+nBzJXiaw z*@AoUCrL!C=$MQb$h^V$)YT7M9!nd7U16p&S$vKx81Tq-&=>zT)`$cgq2=<2=7 z`zTtAr_z0>lPTRVJdB*pyiSxGXcClBdVt)rL&z7JrK$^0$8F8Zx{(7?&+93yRoMZ= zWtukkc|dhGRm_=E!WwZE3EItrFl!UvKTg$3qHV{^ocCA%$-^v^=abTtQh2uF-Z)!^&C3b(^-m zrD=7IaV4#yg~L1SkO$}tjs@fwTs!Y6%fsL?C$5rM;jso&2iUcfvOv3pbL$lHu=(5G zpj-s$Y~KybGDDtaw7jrB=@WUDvd$cJN*+HsqNa>>L4B+3h_k=3a-w{WAMFp$XRdfG zm%WWNs4Yj(?ja-zrLylzHD;>&QRSf$VA-%W;K)+ooC<6P=0cl-iw&DxU5v6d`JarLOaY# zG^K?vVVWvxV$M>~71jpgu5?TgmTYgRILT#C!^driRJXPF|QUe>! ztu0!OgB6c9plm~|QLF>{MB~M=v;2D@8N=9?n=(@T97I_dL0EBgT~OLM544`cBFocs zm^jM{J({O8=!byMdIU5r@qnhzax~T|&RI$TM_^aMlO0KFG0t|Dn78IwX85EvSe9bL z7FY|ka~hE&bs}dEr9=G}qvWt;mWCNt%O0Yva-1~QwRT4yxK-d(iNO^VtHfV5>hN;- zAedj$Y%r$lPID)IY&y@o6Wk4OuG|Fv0Dic5qn=)aC(<|J=?>WMo8i>$X! z6By*=)p3rTLhU2v#NbX^Z}|bYxTH69)Rwi}@B;eH;6FS6Rg)zCptU+ry zN_h^)F#mi9Mt?KPJc2Rvs@7mH(TgV_Ar6Vl#=7zf~g>4t0{KzKJiWqY7k zs`0bv+^<-xmTQVx+NOCx`K9*WjJSB+8c$wDAXzMh79(}iA+(6I0<)&g&Lz&IVBLB- zv?cZC5b_z&tVm#Q+KBld>^P~nCgA?GbIN<=X2ksU{%w~la0gt1*I;LSEoRYn%p(3> zXT0p=%+wZQr`616?n1Sx@Yt{vnr79(^{DLZO$b~IQ6DXvM&|{Wtio`*0_fr8gq~S) z(7`P0K5Xglckyg&Z<{seXaG^M2Q_;+YTAz{8i1QM7}lT}GT!~swlcq&CH~)NYfw{L zU$)P3yoLGFEk*ye*LJB^oJQ?W>EGr^Pg|F1UiESl>@B|m6DClbnXYZPRqAUbzctv>dIxR1CZY%_Xmn5^x$h zz8p)lOS3r7WA6rhZ)Ki;7ixVE{%9=Fpw`rfX&&U|a*w?nD)2u1!I9-0(V^?wJ>P_J z*D1^zOzjoWGzzqj480ieqw5b0cZkFAga=n;|Kb%G#4RYj9U|LkDxkBgO}UwiHG;iEn+Mvrg89*Ep})`VonqG` z*E{fc1iJoC9wGtn6vAc(jeQ-EyM#NDnuv)I0~Nyxazn66MpyScu^!A^wYT8JCHn79 zuK1fTH??A4ak;T?HQu&X)b%*p$Xy^O6VE$12?H79KA;g#winQ=op}##Bh-dn2CPib zryor>233?)zEs8(Y@PsceECc@hy3p7ii}=x=3@O5)=H%vVg1uQFG)a_m<#uG+-Fgl zQ37}@$(rVCguIRUlUHm#w&!h|c0M-$`9xE?<9bv6v3u{lZRw8bH_urZulC|Q@KI|& z7UH99VLbbDug;V%jBobp5q6bdQ(ws_3u~{lxhll(MDm(=Uu;h8F8uAm-(LK6$2ORnk_{-Hu!pdh&|Nj(^A^SzdMnHd zQ$64F1A2w24W9zuy!pPr0Q)=P^ zH8p%f+l^Pdrv|M=gbvhjUr7ZEj2LOG7DgX(&aX zxS|l-tL>@1otgJk0xN5K*rzS((-x5NBP8QT*q_bF5otxlk6_ShTQG1(*e@-B_z{0j zc?o5w#3T5C*ZjXc4_z?Z8SRefImzW7_GVxI|FRvyx$cf%rxF;Ugg>VqAITU_a`BnM zrxmK6*qjDY@c{@zd>}pm5vYkDq~t-&2KWh~KcCV(DIG9YOj#X2F{0yWdez>Nr z(Feu{${S<))I_s-0#nl|4o2O9sD|^TrUK$cBECa{w$?s#9+V)YT+BYp96}^ensf0T z<;>u2uqdVDipMN`=pyKp21I~H;hzs~IrJ5{_`m~#N;d#&$~M?KV6vCv&lk76tg!^M z#+L8a;&$St{e@&Kc3CiL%GGX50FAF>iLNtpWy76 zn8S&beKTu^fV1_a@_c!Qi>rHJVFrAHS_VW97$^C$FmQYn^;3>Luol?zURjvF&{gezabXSJ`zt=AU>KNi>HtRB9}sx8dNET+{#OlTRF3ygU_1sa*81z85#9% zK)8=aFi}hakly%OECD_+oe4^4wFd4!cWFM@-Bq@n!pFq_(h0tJ;kjP4k zcBKTk9UX6_o0LDNlCy*)Lh9*|dWxAHluRF-ik z<-1knW302S0V{875KtE?0_y3IdWvZeD($CK%v1^e0k?72_Urw7sVz8#`b)NLHTjkn zwi{39T^ME-pO6OYsaNk;1H;fK?bEX^E>%GGacIv`BD)b>z3YOz+pHo#JkM^l^qGV6v9M1WNRnh5^e zEdOm9%CFi6d=+^y>IOz7`8H+#RjQ{iL+6yT?5|Q1t-6O8JJETu4xO5t3scec$@6$x zvK2}`&kSa0ZmzoHc|@*;#tzuo=gQDa2f!Z<4b3e*f4Lr+vT zLSu;1TAF>Xz6No@s+V{@SKnX<{W+B2QrBaJV48ZUeiaIZk$v9Em`HXuYR0K&YZg#X zXfWO?e3Qa$d`|Y~)S&Eh!BFJtnGK%Z49?YKykPEQ`X`si2R&wdFd0==4XhD}F=iu(YIe+XRtX=esj+gew%|!K z8GZbO9Ttggo_qr1nrmbiDIg%8AQ2J%Y7AUGMc_Hto4I;;D^#gE%!nniIgs2&uZEHw zPf?O#c0kBMn%W%fMJTu&tV>ut&{Vk{6yuzXOPF2t%rkotJ6lAkFUR5^Sc2NolIvR= zx7NcTV{0}a79pl!tp^(sLZ@9ZDBn^LCa=Mg<#QSDZWjd|hR*-q{Cd;}#1Aps@$nPv zAgK~S{%k%nB=3cWdK#UeeomKd0{bBt;%zHCvkYR7llW z3dNMe)I=5@8TiEGeDosPk=p~2dAJ(;N09NQ_?LYc`MIa;!-$N@Y(E(j<@+4w9Ja_9 z);(BDG4OlH*(=W8(sJ^Jd*`5o&~@l1nR|@YH;*!z%|S8-k#p_@M4>)jfgz1Iz-UB> zBXb~;J32VWL9SoIp||SyJZkbQ4iP@jE3h8sJZP4p0F-ckp;*zP7|1%@8HYHb_-NSN zkQL7jNKfSMMDfTlSJOy2wzb70m;YRMJm-lx91!53(Fg*kRLj|US6=pgC^Va6$=!s* zHv3Zh;Z<7Mt}}HWWvtH3uk#R82UTB_mrVwvAHhWE28Gf}s;P&$?vp?4egJ0DL3DbVKI1!Nm&eMya)^KpT@i+^ zFeuV`wlD&S09O}!dj&iU4fTxtnlLL;mJ=j@jct%?*WLDsUa-nCRGF1p0o82a&5~BB znNx-h9>$4l#={u%$}+6250{fS&ywg)+qD`{XgLfkYR*pOP7xxYT`D({lrhADu%QK5 zll>Zh$$URXPaP}7PjKn5LyIaAiY|=jvJ@+B4xu3)K_6F@AzM@e2ub%Eu*E}VAc=qb&!_VSl+M|K7awugQg4hiv3* zMkS^=2e78Bj01^1z3sA?ujw0OkD=>pVl{K~Gk*mxHF%n*NT+^?`F7wC591T7L8aj* zMW_CPXY4-rBiVtWi@8Ifz-N3=>vNF}g_Z#XPuv9`L=Q(zk+nt-i|Sc_o=oA8R37-LG~29 zkk*THR)#h`hf)KV{V9;i&>pL>$0Fd z!+gk64YCiSOs>v@YVdiYp5mEIAn~#-&IV>%S_RLX;?ARlnA0MRs zrE=8-3=>8L?gj83h_G|NgLr4_nYg@~+U~4|AD@*d5p$VK%>pVRcp3+xMY0dL+F=qP zDf$+}@(`Q#AQ}L1I2(?|+48WCI-I=qkD$kr*TIa z7@aWqp?L21XKAu)Z@z+TZ%ys(VUv-ut9ri4G%Ej)Ep?038VWSK$i;M3%1yd~J&Wn| zhZSYc)%{SUR;cu!L>^Je_flMH&opq=fzO1Km0n?d%2`~A^#(Kb5j^`#jC6Y^#p+;C>{7>$M~kCj)ImD#8A@|e{= zu@a0>thTHQQSd+Vq1^-*Ix31v#K3?B!%Aw3tcBdm#csE>XEsuaHpUth14Uv{MU_f` ztUc8aeQQv@)n#*_YVe3!G?Zd8$L65Itacgl2D41{ZHU1*QB~L^tYNlISe2n$$}1X6 z=}bq~6=gWwC}$z)9H6vstVa5LZBOm ztc_3jSnJrsvZEl7XSP8usW{GDg=G2j&-hZ#%nG}t#VdGRfDJPDfe=m{onX(2PZ}7A z6wmzyIt;Fazy9~US)N01jfqV`Opp1TT^@htxb+m^1U+?4t%S%Z`HGk3?&B;#jN_2oX=fqG*6 zzC`76X53~40tM46^Q2}ma(I#%pE<(T@<@R}af%*`a8cvA&$(33mKkJrd;B0{)}EQb z$aucK;9#B6#6$fz! znv#j1n#V>$tGLm+u!voC0R!lU&3-(sGTw~rYMID=KC=V{3^L0;#RcXWcJw$b3CJcI z0y*Yh85>X7?U+Q=ftUw&ia$={p$C$T!tIcKwH(Xs8A!sD)TBqWp~BgJB{~W;d;sh( z`i$!9&>J(Ix`;yWAD0EXW^;x{MCfp|Qt&JTz5qCLmeiNZXg8dBuwHZKDQQlghStUC zaH#X^DEU*?frvWhzJ$cE6T(cDY{`6E4*0yCg3>FPt6aqBq}$IT2y@I`z=gv5oj4oz@( zX28Kh6CYU!3(iW^i---9a`9py7caVJbXgXzYp(9_%pwMc`^C^yL&|5weQE~xDRCiB z1#vG(Lp>vWN_ZhK!ITqC3lb6LQ?kpzd@91c5HLC4D4D^$d%~ID*(Y4U(|44`(YMwU z6wgg_FQiF?QY?jP@7XLpXB^ET__JW&Uh{ry?O^C%*8=)+A0iG*Cjdc!1u!+(kqX%Jfz`I}6XdzJ&z z4m(uRh;zt*gkYku+z%jH=)N$9 z*FIRN9eNQ%`k)(CyX`{nj$=%rrs`!*VJsiVSlZEC0He|Fd^Ni)i4v&-;T-2Meo8}a z>GPuNU@Y61oROAdc$)s?XKV=%?pK)7PO`EaAyl7%((tkZaW91{^0FWtCOs71-6!twzVng>EXaL%?9wp7{xJ_IP5wWy$ zImqFEn8H}p1KSvBz-z!CRGI5+oPOB;=P?KmM(cq%vVwunxr}>-l#c(uy|d|QA_(L7 zv$gdtron26QPeqLf(hMh=|-qZA_58rp`n}NfvA)gG^v2a7!H`UG)BLP=}m7Y#*254 zCLX-_3A{og>i<8pFO(9)9S3%Ic6VN%*`3|a&hL4+e#Y@Vyf^ezk6q}&Ly3bh2;u*~ z3>widpWa29_~$qX(oNN09rq)k>)}-ww0G!3V2oumryu}C7B>T#jh#NWEut~wP!2&p zyVKx1S<;LNv{Lm}=xgvMYX9WImyhiP#-cF38=S<)m&8#P;0(UrY;IG;n>*aUc)Dq^ zpKX*=jV;srn8x76sk^PlFWnns%2leVM?;#4n9jbLzyWKpf}CB3;p$8{Gc%Vsf69K{Hu zYpa4wMy0)nG=X;YT5`GYghn3J%y_|5(DY#nk7P3NukKK0t$VYQS-F=>aD*pi7N%vnmhibc^tQRWM{O8W4HNKgG4m}D*$y28KwYnu)T7a<49iyYr!=`*-ra;5aD6YfxNh9r2MaP8#$TW z%79Nul|?n)U$#S9w(W8DN_cz{FWx0mj3H||b7HuJu=gCCoD z)EQ?sde_&3x7AO6d+(_yuUi*v=so51-ulLMy=SiL-T$z+_P#wh?eu|c)|(SXefR-} zad4Yu%(&#uhwIc{G|ZXlHrFurH4Vd2=!}y=_kteBler@elKJL8{WKl`NEZCFj3w_j zjLGu9^$eYg#n^h1X}pE>xM@5?K}`I2gK1=dtpwk+iGKge-D?;qLGzyr_tK`zFa|c9 ze(nai=j?;b!cWQ?=3BD?K53xdsGkZz@`gN0LHCa{E-{QH1NGC_24G}f4dmG%%hDbA z_N901ALWXF%$sQ>j5}U6jJwvg8Eu08_dmy&ez#$Grag*yZPOY>M0Ry z)Sw3pWkj8yXB%hX2{dO1KQIkv3^icaa-G{9)Th&!3dV6lg8SgB)Ry?uf!6V}-W*}% z<_J^rX8;XK`0;!3vTxPW z^?eXQ18VARLMf0PySxBtkqBN!JmneYNP_4rcnbjl%Blb%03Zzo2mt^(p#UKOq%<2mq*K6^9T2vKkNqK)VKn05C}dLI6OkP;m$WAg2K#0CZ?T2mpBv2qE=n z8oS{M`R5vgkY+kr2#_ZS4gbnU=o`V9&7w z)Su%h{V!(L&&QNlzITYPTY3Kn;*N_0Qde@g6Xk#|=NjKfYH3svD%A-- z&7{qsi}Ys{4W)B}uPPeqrh13BIQ2KGF}7_RvHfe;&wk*$k$kA1Q8ci;@?b!71?d55`X|ryTVa zXubg=@yZ42(p1##;iiEe&d6DI@F-d^1?_oGY3~4<=cSWf11YDF41A(?@I!EHMutpb z3!o}qw(&QlkhiViYw#R{s;Itd2&n3-2np^ZsY*~mpuAi0b8b*2naJ6>g!F`X^q?RT zcjH8a4}OIo@YTRq`|h?(&aEcl9Dwurux~`IsPuMgrblRuKauoONH3+*bC8~+(sOp2 zUaFN|3hAX(dS-xD>EykfcK}pGMiQi9?14WB$EX~baDs=ykw~H2{x*nAWg(z%Xy`G4 z`lHa}0_7RP3BD^1r!g0W+hhjRuzWg~J^(Uf{TPsyF?<7la(4Y~s75zEoYCRuTj$49gGcVk2g+8a33wW5+DXIpQ+5wWdd|wUOs8(lA=g> zoP&RswsEiVnDnYpoQZbFd*!?Co{F=rK#_pYM8I%Bc)||JO zDKthw>Zv8a0kj6ApoKmVBaQrvs_~$y@^CN$)cPjsbW_XU)70{!*7JmsZ9^bPuYL`O zFldYCnE{5Eu!WSJ`pxhtUIwEvW{M6 zeI-$U3Xi-E-R)L6baQSYB{I7)=N3~U7f_LGB04CiSG#Rndq;A60fWv|RY9tOq1`3e z2eiS%G_EyPzGk#j;4{=<4;w()EY>JGBbx)eJTb8Q$gopB(ysp!c`})2rx;oht3zK? zq-^a}!19aICZpE_mCLrhhmXo_EUB4R&_7-bxWtH%6FDxu zucpJ24bYD^6WW%6PBT~9-Z&B%YGd@RcskbTQG9^MGN4iHj9^yi9HCz#KgtPsty3 zv5NF3v3`TqfYX)sWbiifSxx{cdr383{c4++tU5{68H$dZC{oW%W?k8VKAuqhoE4nO zcnX@F{zW{;s7Qrmxh@N%Su%WVqaaXbi@Fb=!4pp+bE~XvgMo8&E zz6=Y@#z1dJ#}Ta?rcpEwTBXK%&Kc$*KY8TG+>Bg>_F{naJ*Pf}g;@_8=H)!oDLcvf zY(gl4YRkJIY$wC^dDUL0z6(74Iy`HWocbP3hh4D?QTNO_{~uLJ*S;Qv@#ptvZc&F@i8sOqoml*Ci!V&l#JJQApN5(9JrH zi@-QeNN^uEU1e;B=0FGRG%%`qxfbLw%zKpr^eSd_ZHt0(o^OE&9 zCX4kzp566^Jg3ypk!MdG%VO{!->VrY;}+@{5Oj<6_sFxm{(gB*sb3?{p8ECj9AAt; zJ(scRcwWwnylJKAv4Cz_hmaw{~B->(v^O6 zc()?vF$O9K8C(mm;KTgcf}iW8`*+aAKfTR!t4_-Q2+-%9#z*lehjx@_ELo<;tO5Tz z;66Gt%DjzZpwY{^@>c<(8h=c}vHe17?6=@I224$akf*6*luQyMk~_9osNj0|t8qyD zkeTPg@#d8JtH{3TyJ$SMlv(QA-p05!GI6$tX(phVo`Hd z|7K*U)}fdz#YzavF{gkz!i2Kh#t8C+2ADG&e}yjuu#Ya?g>b9+AtAwKewc=h@-qDT zow0p2@4Lu*3nf8Fa6b)6IAi;1mW#-;fGmUrmpLh{B9O4;k_Bdc$=Ov!~S64`sctY zLu?fYxk`s`Z>zKwvZ4Q%n*NiNfA1ID3`1Bj>rHASr3S;Nnyh~l+?6&rL`|-&d7&d5 zsi+60aRSPUF0E-3(f&|sa0G;uw)~^;@Hg@2Z2YvmGPZxNMzhW2b%Lo_S_5XmvOE0? zz+WCfmz)UcvRS}t=qO>z{d33*dedCHElYCMr1Ybc!NQ~`Tfl{|O0FKds5CG6=sUSiCSgrvf z0Ibk}5CG7#sUSjVs}UX;4wQ!w09I;12mnx0#UTU$^w|m!0>FtH5CXtS8V~{idM6b` z2mq&OKnMV*YCs48r)fY402t9#96|tCtpOnbptDpQLI5~J13~~eQv*T(Sfc?UV5fA- z+GttXQrn^2yRa|vw?a+rT2j`MCyRORcs^`*CvBqn`%ip(_Z*1W~rc1V>9uaNLD(!6o>~!7)K*Kw2`x`lJ#X`b-g;<0_$n>vn{nAT*%& zGU^Y7QB#6SX7Fjr433t}q;5m~DK=&GBtrg&vicraF){3C|0ue&Gg*l){W~euVQQ?W z+LQ$6cqAZUH z3!xT^Bg=rY21VOMwt%x^i6=}{znyO$@sVFiB zGwe;M?8^Gb0`Ni8az)SbC!s31gHgl|MiyIC6iJE$r*~p&3*)CwHHoc^!gfBU}hI6(2|~|$?{dC)be_Ou0-lK6N8f>G`C~XBC*C9URYxZP3C{>Q6vSzEo&3n& zs1N`!15$tx$mXLg06aEm4PUgqak?DyJ35(8Kr|K_L(E+ z=7OhNRhnC#?bE+bZ1#JnTq{O_(a0Tw;Sm;g-Otbj>u_c6VnT`AlE@u^rLM`cy}`f+tX@ zDq6Jo1y90N7ESIZg*FLuUm60=i=Zc^K68sA8g=(1AUT z#~5bWYCM{Q%r(9TXq=GXKBQXlJJ_=%gYUyDpBlaz`R+*hKY$BoTAslp>jpohALh8G z--B3uEP6Y+WNlIogT;3^SfCl==u0l?=Mfht?KP{j(w=iim>(PmW2tx;r@Al|JP*3s zn+h;md0R08w24moXr|ayN(C4pyuy~OYndsW)|rKrI)fL1Ax~)1-lCJcDX z2Fv>|;R%HS^)e{Q0~Rka)8TZ;10!aQ#aTW$gmeK08RLw&*DDSy2 zF#Ew6I(wsjdDBfPc_pw!qBxK^<+bP>R@|JNv+)!}PGy1Y!p(cfbZrTyLa+&ivOLDP z?58q>Ngwem6lfvjr1kK(h!=uVg>vdkVVFl_+u9 z+6oy)HPCemjo*V2J`;q14Q^{|SB$&XVQn3aA=NX{y&+=NJ#`^1y22D+LA;p?o4RCR z3w$yYqpT)fo~LL-TJe|{B3Fj%zlu0E(+3P=@uWL+#D5?UJ;8H9oM);UEo!dQ_#?O~ ziLuwnOfE1N;>;Px{}X))Lw=&lr&^-Q+0@o_oH@l^O!mIz)K=(nTclO@t2S5I!Y*W@ zSf?@^dsrOZv3;B$h!CAn1da{JfU&6AJ}_*nwj1`h7-Aq0HRcEb0Hs%e5CBj@1qcCP zTmwSHN2MBbfi$`9@?|{tVA?X!)Y2Wc8fLNJ7mhD~hK$hL{sj*VPW=e0YQIlm)#>V~ zyi6ZQ;T-=q`~-hhAq3!XR!hPl!M2|xV<38>$gmd^_~qcKPBUE@B$FxWo>Tr1P&JxY zvf9s|56~^6Bl=$?RzpYhH#~#C;?wVgg_j@v`4EXlh$f(o&P^wWq()_=c(&VDZ`dt@|DC-cQZzI*t? z@XQr+-COh!n+h@rxNroxDgZO*A;{D(y}OdfVC=YWQ84N91~_&AZ@IL%am{7mz!ZOD+7Z3Gv|EwA4>K zWA;*<&v-JrTDi0usE6-GuyB~4zw=?fN2i^|2*9yKOxQ(yt0uMe z!g%MgOUM#TVg@i_&1L+_AUBgQOp&h)rPMGm6%5Ig=~s~_pMzS+GE-P&2$+)!qYSw? z5aeNS-8__$Le(lbDf^;U-~-j~!JU7b!E7Z28rh z%`6cMGsf{k1_PWbp3-EHlI17?Mwm}V(%DneL6;Zpef@aI=HL(u33Wk{(Kkjz&I&`y zP$6SPEX?C*!(lxKjmKz$Vuj!Z%H{I8T+o5sbM>V%%7zmHx%_tL zaT=4bkv)G3RlLK@P0DrTCTk6wtmIiaHahx9XE+0c2kbNIlIjTaosdgs$iItSozu!g zSFWqt1?#fQ-;Fh20AoQh=DM-c-JR>s6)!(?@0G8=@do-ut`RIiNf)EV+R}SvD&4N? zx=hQFIMRuvvRuN|i5KI`0%8A=H0D%P|G{wum22#cIPqdl7YZB-4t*P&eA@AQAb^Zp zMF*i8xY?hCkeT}dI{t@Qo{{≠0S1>^uhm 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 Date: Mon, 25 May 2015 14:31:55 +0800 Subject: [PATCH 02/72] updated ApiClient of python sdk. When create api instance, if we don't pass the `api_client` parameter, then use the default api_client in `config` module. --- .../languages/PythonClientCodegen.java | 1 + .../src/main/resources/python/api.mustache | 9 ++++++-- .../src/main/resources/python/config.mustache | 8 +++++++ .../SwaggerPetstore/apis/pet_api.py | 9 ++++++-- .../SwaggerPetstore/apis/store_api.py | 9 ++++++-- .../SwaggerPetstore/apis/user_api.py | 9 ++++++-- .../SwaggerPetstore/config.py | 8 +++++++ .../tests/test_pet_api.py | 21 +++++++++++++++++++ 8 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 modules/swagger-codegen/src/main/resources/python/config.mustache create mode 100644 samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/config.py diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java index 7896bf66878..590e17f6326 100755 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java @@ -71,6 +71,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig supportingFiles.add(new SupportingFile("swagger.mustache", invokerPackage, "swagger.py")); supportingFiles.add(new SupportingFile("rest.mustache", invokerPackage, "rest.py")); supportingFiles.add(new SupportingFile("util.mustache", invokerPackage, "util.py")); + supportingFiles.add(new SupportingFile("config.mustache", invokerPackage, "config.py")); supportingFiles.add(new SupportingFile("__init__package.mustache", invokerPackage, "__init__.py")); supportingFiles.add(new SupportingFile("__init__model.mustache", modelPackage.replace('.', File.separatorChar), "__init__.py")); supportingFiles.add(new SupportingFile("__init__api.mustache", apiPackage.replace('.', File.separatorChar), "__init__.py")); diff --git a/modules/swagger-codegen/src/main/resources/python/api.mustache b/modules/swagger-codegen/src/main/resources/python/api.mustache index fc779a66653..2ec09d92681 100644 --- a/modules/swagger-codegen/src/main/resources/python/api.mustache +++ b/modules/swagger-codegen/src/main/resources/python/api.mustache @@ -31,11 +31,16 @@ from ..util import remove_none from ..swagger import ApiClient +from .. import config + {{#operations}} class {{classname}}(object): - def __init__(self, api_client): - self.api_client = api_client + def __init__(self, api_client=None): + if api_client: + self.api_client = api_client + else: + self.api_client = config.api_client {{#operation}} def {{nickname}}(self, {{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}**kwargs): """ diff --git a/modules/swagger-codegen/src/main/resources/python/config.mustache b/modules/swagger-codegen/src/main/resources/python/config.mustache new file mode 100644 index 00000000000..e8c36aee77b --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/python/config.mustache @@ -0,0 +1,8 @@ +from __future__ import absolute_import + +from .swagger import ApiClient + +# Configuration variables + +api_client = ApiClient("{{basePath}}") + diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py index a599aeaabc1..83b878f8f3f 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py @@ -31,10 +31,15 @@ from ..util import remove_none from ..swagger import ApiClient +from .. import config + class PetApi(object): - def __init__(self, api_client): - self.api_client = api_client + def __init__(self, api_client=None): + if api_client: + self.api_client = api_client + else: + self.api_client = config.api_client def update_pet(self, **kwargs): """ diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py index 7f9b852f7ca..ee3ed53b032 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py @@ -31,10 +31,15 @@ from ..util import remove_none from ..swagger import ApiClient +from .. import config + class StoreApi(object): - def __init__(self, api_client): - self.api_client = api_client + def __init__(self, api_client=None): + if api_client: + self.api_client = api_client + else: + self.api_client = config.api_client def get_inventory(self, **kwargs): """ diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py index 2471970c436..3fffde5dfc1 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py @@ -31,10 +31,15 @@ from ..util import remove_none from ..swagger import ApiClient +from .. import config + class UserApi(object): - def __init__(self, api_client): - self.api_client = api_client + def __init__(self, api_client=None): + if api_client: + self.api_client = api_client + else: + self.api_client = config.api_client def create_user(self, **kwargs): """ diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/config.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/config.py new file mode 100644 index 00000000000..6e158eedd70 --- /dev/null +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/config.py @@ -0,0 +1,8 @@ +from __future__ import absolute_import + +from .swagger import ApiClient + +# Configuration variables + +api_client = ApiClient("http://petstore.swagger.io/v2") + diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_pet_api.py b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_pet_api.py index f0b8ab03d81..ee8c5dde14e 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_pet_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_pet_api.py @@ -13,6 +13,7 @@ import unittest import SwaggerPetstore from SwaggerPetstore.rest import ErrorResponse +from SwaggerPetstore import config HOST = 'http://petstore.swagger.io/v2' @@ -49,6 +50,26 @@ class PetApiTests(unittest.TestCase): self.test_file_dir = os.path.realpath(self.test_file_dir) self.foo = os.path.join(self.test_file_dir, "foo.png") + def test_create_api_instance(self): + pet_api = SwaggerPetstore.PetApi() + pet_api2 = SwaggerPetstore.PetApi() + api_client3 = SwaggerPetstore.ApiClient() + api_client3.user_agent = 'api client 3' + api_client4 = SwaggerPetstore.ApiClient() + api_client4.user_agent = 'api client 4' + pet_api3 = SwaggerPetstore.PetApi(api_client3) + + # same default api client + self.assertEqual(pet_api.api_client, pet_api2.api_client) + # confirm using the default api client in the config module + self.assertEqual(pet_api.api_client, config.api_client) + # 2 different api clients are not the same + self.assertNotEqual(api_client3, api_client4) + # customized pet api not using the default api client + self.assertNotEqual(pet_api3.api_client, config.api_client) + # customized pet api not using the old pet api's api client + self.assertNotEqual(pet_api3.api_client, pet_api2.api_client) + def test_add_pet_and_get_pet_by_id(self): self.pet_api.add_pet(body=self.pet) From 2d545c7f0bbaebab613ae6040e17167d3b5acc4f Mon Sep 17 00:00:00 2001 From: geekerzp Date: Mon, 25 May 2015 15:29:31 +0800 Subject: [PATCH 03/72] updated ApiClient of python sdk. Change staticmethod to instance method. --- .../src/main/resources/python/api.mustache | 6 ++-- .../main/resources/python/swagger.mustache | 23 ++++++------- .../SwaggerPetstore/apis/pet_api.py | 34 +++++++++---------- .../SwaggerPetstore/apis/store_api.py | 18 +++++----- .../SwaggerPetstore/apis/user_api.py | 34 +++++++++---------- .../SwaggerPetstore/swagger.py | 23 ++++++------- .../tests/test_api_client.py | 22 ++++++------ 7 files changed, 72 insertions(+), 88 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/python/api.mustache b/modules/swagger-codegen/src/main/resources/python/api.mustache index 2ec09d92681..d5e24398f0e 100644 --- a/modules/swagger-codegen/src/main/resources/python/api.mustache +++ b/modules/swagger-codegen/src/main/resources/python/api.mustache @@ -29,8 +29,6 @@ from six import iteritems from ..util import remove_none -from ..swagger import ApiClient - from .. import config {{#operations}} @@ -76,12 +74,12 @@ class {{classname}}(object): body_params = {{#bodyParam}}params.get('{{paramName}}'){{/bodyParam}}{{^bodyParam}}None{{/bodyParam}} # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept([{{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]) + header_params['Accept'] = self.api_client.select_header_accept([{{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([{{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]) + header_params['Content-Type'] = self.api_client.select_header_content_type([{{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, diff --git a/modules/swagger-codegen/src/main/resources/python/swagger.mustache b/modules/swagger-codegen/src/main/resources/python/swagger.mustache index ab45eace646..21430c469c8 100644 --- a/modules/swagger-codegen/src/main/resources/python/swagger.mustache +++ b/modules/swagger-codegen/src/main/resources/python/swagger.mustache @@ -66,28 +66,28 @@ class ApiClient(object): if self.cookie: headers['Cookie'] = self.cookie if headers: - headers = ApiClient.sanitize_for_serialization(headers) + headers = self.sanitize_for_serialization(headers) # path parameters if path_params: - path_params = ApiClient.sanitize_for_serialization(path_params) + path_params = self.sanitize_for_serialization(path_params) for k, v in iteritems(path_params): replacement = quote(str(self.to_path_value(v))) resource_path = resource_path.replace('{' + k + '}', replacement) # query parameters if query_params: - query_params = ApiClient.sanitize_for_serialization(query_params) + query_params = self.sanitize_for_serialization(query_params) query_params = {k: self.to_path_value(v) for k, v in iteritems(query_params)} # post parameters if post_params: post_params = self.prepare_post_parameters(post_params, files) - post_params = ApiClient.sanitize_for_serialization(post_params) + post_params = self.sanitize_for_serialization(post_params) # body if body: - body = ApiClient.sanitize_for_serialization(body) + body = self.sanitize_for_serialization(body) # request url url = self.host + resource_path @@ -115,8 +115,7 @@ class ApiClient(object): else: return str(obj) - @staticmethod - def sanitize_for_serialization(obj): + def sanitize_for_serialization(self, obj): """ Sanitize an object for Request. @@ -132,7 +131,7 @@ class ApiClient(object): elif isinstance(obj, (str, int, float, bool, tuple)): return obj elif isinstance(obj, list): - return [ApiClient.sanitize_for_serialization(sub_obj) for sub_obj in obj] + return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj] elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() else: @@ -145,7 +144,7 @@ class ApiClient(object): obj_dict = {obj.attribute_map[key]: val for key, val in iteritems(obj.__dict__) if key != 'swagger_types' and key != 'attribute_map' and val is not None} - return {key: ApiClient.sanitize_for_serialization(val) + return {key: self.sanitize_for_serialization(val) for key, val in iteritems(obj_dict)} def deserialize(self, obj, obj_class): @@ -253,8 +252,7 @@ class ApiClient(object): return params - @staticmethod - def select_header_accept(accepts): + def select_header_accept(self, accepts): """ Return `Accept` based on an array of accepts provided """ @@ -268,8 +266,7 @@ class ApiClient(object): else: return ', '.join(accepts) - @staticmethod - def select_header_content_type(content_types): + def select_header_content_type(self, content_types): """ Return `Content-Type` baseed on an array of content_types provided """ diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py index 83b878f8f3f..ad4bad57412 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py @@ -29,8 +29,6 @@ from six import iteritems from ..util import remove_none -from ..swagger import ApiClient - from .. import config class PetApi(object): @@ -71,12 +69,12 @@ class PetApi(object): body_params = params.get('body') # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type(['application/json', 'application/xml']) + header_params['Content-Type'] = self.api_client.select_header_content_type(['application/json', 'application/xml']) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -112,12 +110,12 @@ class PetApi(object): body_params = params.get('body') # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type(['application/json', 'application/xml']) + header_params['Content-Type'] = self.api_client.select_header_content_type(['application/json', 'application/xml']) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -153,12 +151,12 @@ class PetApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -196,12 +194,12 @@ class PetApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -243,12 +241,12 @@ class PetApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -292,12 +290,12 @@ class PetApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type(['application/x-www-form-urlencoded']) + header_params['Content-Type'] = self.api_client.select_header_content_type(['application/x-www-form-urlencoded']) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -338,12 +336,12 @@ class PetApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -385,12 +383,12 @@ class PetApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type(['multipart/form-data']) + header_params['Content-Type'] = self.api_client.select_header_content_type(['multipart/form-data']) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py index ee3ed53b032..e973d3a6ba5 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py @@ -29,8 +29,6 @@ from six import iteritems from ..util import remove_none -from ..swagger import ApiClient - from .. import config class StoreApi(object): @@ -70,12 +68,12 @@ class StoreApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -113,12 +111,12 @@ class StoreApi(object): body_params = params.get('body') # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -160,12 +158,12 @@ class StoreApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -207,12 +205,12 @@ class StoreApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py index 3fffde5dfc1..82874000d59 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py @@ -29,8 +29,6 @@ from six import iteritems from ..util import remove_none -from ..swagger import ApiClient - from .. import config class UserApi(object): @@ -71,12 +69,12 @@ class UserApi(object): body_params = params.get('body') # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -112,12 +110,12 @@ class UserApi(object): body_params = params.get('body') # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -153,12 +151,12 @@ class UserApi(object): body_params = params.get('body') # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -195,12 +193,12 @@ class UserApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -237,12 +235,12 @@ class UserApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -282,12 +280,12 @@ class UserApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -330,12 +328,12 @@ class UserApi(object): body_params = params.get('body') # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, @@ -375,12 +373,12 @@ class UserApi(object): body_params = None # HTTP header `Accept` - header_params['Accept'] = ApiClient.select_header_accept(['application/json', 'application/xml']) + header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: del header_params['Accept'] # HTTP header `Content-Type` - header_params['Content-Type'] = ApiClient.select_header_content_type([]) + header_params['Content-Type'] = self.api_client.select_header_content_type([]) response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/swagger.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/swagger.py index ab45eace646..21430c469c8 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/swagger.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/swagger.py @@ -66,28 +66,28 @@ class ApiClient(object): if self.cookie: headers['Cookie'] = self.cookie if headers: - headers = ApiClient.sanitize_for_serialization(headers) + headers = self.sanitize_for_serialization(headers) # path parameters if path_params: - path_params = ApiClient.sanitize_for_serialization(path_params) + path_params = self.sanitize_for_serialization(path_params) for k, v in iteritems(path_params): replacement = quote(str(self.to_path_value(v))) resource_path = resource_path.replace('{' + k + '}', replacement) # query parameters if query_params: - query_params = ApiClient.sanitize_for_serialization(query_params) + query_params = self.sanitize_for_serialization(query_params) query_params = {k: self.to_path_value(v) for k, v in iteritems(query_params)} # post parameters if post_params: post_params = self.prepare_post_parameters(post_params, files) - post_params = ApiClient.sanitize_for_serialization(post_params) + post_params = self.sanitize_for_serialization(post_params) # body if body: - body = ApiClient.sanitize_for_serialization(body) + body = self.sanitize_for_serialization(body) # request url url = self.host + resource_path @@ -115,8 +115,7 @@ class ApiClient(object): else: return str(obj) - @staticmethod - def sanitize_for_serialization(obj): + def sanitize_for_serialization(self, obj): """ Sanitize an object for Request. @@ -132,7 +131,7 @@ class ApiClient(object): elif isinstance(obj, (str, int, float, bool, tuple)): return obj elif isinstance(obj, list): - return [ApiClient.sanitize_for_serialization(sub_obj) for sub_obj in obj] + return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj] elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() else: @@ -145,7 +144,7 @@ class ApiClient(object): obj_dict = {obj.attribute_map[key]: val for key, val in iteritems(obj.__dict__) if key != 'swagger_types' and key != 'attribute_map' and val is not None} - return {key: ApiClient.sanitize_for_serialization(val) + return {key: self.sanitize_for_serialization(val) for key, val in iteritems(obj_dict)} def deserialize(self, obj, obj_class): @@ -253,8 +252,7 @@ class ApiClient(object): return params - @staticmethod - def select_header_accept(accepts): + def select_header_accept(self, accepts): """ Return `Accept` based on an array of accepts provided """ @@ -268,8 +266,7 @@ class ApiClient(object): else: return ', '.join(accepts) - @staticmethod - def select_header_content_type(content_types): + def select_header_content_type(self, content_types): """ Return `Content-Type` baseed on an array of content_types provided """ diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py index 9adf7cdb99d..5243430a93a 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py @@ -23,44 +23,42 @@ class ApiClientTests(unittest.TestCase): def test_select_header_accept(self): accepts = ['APPLICATION/JSON', 'APPLICATION/XML'] - accept = SwaggerPetstore.ApiClient.select_header_accept(accepts) + accept = self.api_client.select_header_accept(accepts) self.assertEqual(accept, 'application/json') accepts = ['application/json', 'application/xml'] - accept = SwaggerPetstore.ApiClient.select_header_accept(accepts) + accept = self.api_client.select_header_accept(accepts) self.assertEqual(accept, 'application/json') accepts = ['application/xml', 'application/json'] - accept = SwaggerPetstore.ApiClient.select_header_accept(accepts) + accept = self.api_client.select_header_accept(accepts) self.assertEqual(accept, 'application/json') accepts = ['text/plain', 'application/xml'] - accept = SwaggerPetstore.ApiClient.select_header_accept(accepts) + accept = self.api_client.select_header_accept(accepts) self.assertEqual(accept, 'text/plain, application/xml') accepts = [] - accept = SwaggerPetstore.ApiClient.select_header_accept(accepts) + accept = self.api_client.select_header_accept(accepts) self.assertEqual(accept, None) def test_select_header_content_type(self): content_types = ['APPLICATION/JSON', 'APPLICATION/XML'] - content_type = SwaggerPetstore.ApiClient.select_header_content_type(content_types) + content_type = self.api_client.select_header_content_type(content_types) self.assertEqual(content_type, 'application/json') content_types = ['application/json', 'application/xml'] - content_type = SwaggerPetstore.ApiClient.select_header_content_type(content_types) + content_type = self.api_client.select_header_content_type(content_types) self.assertEqual(content_type, 'application/json') content_types = ['application/xml', 'application/json'] - content_type = SwaggerPetstore.ApiClient.select_header_content_type(content_types) + content_type = self.api_client.select_header_content_type(content_types) self.assertEqual(content_type, 'application/json') content_types = ['text/plain', 'application/xml'] - content_type = SwaggerPetstore.ApiClient.select_header_content_type(content_types) + content_type = self.api_client.select_header_content_type(content_types) self.assertEqual(content_type, 'text/plain') content_types = [] - content_type = SwaggerPetstore.ApiClient.select_header_content_type(content_types) + content_type = self.api_client.select_header_content_type(content_types) self.assertEqual(content_type, 'application/json') - - From f807e34b2b57524feec76dff18eb5662b4309154 Mon Sep 17 00:00:00 2001 From: wing328 Date: Mon, 25 May 2015 18:21:17 +0800 Subject: [PATCH 04/72] refactor csharp (no compile error) --- .../src/main/resources/csharp/api.mustache | 37 ++-- .../main/resources/csharp/apiInvoker.mustache | 58 ++++- .../src/main/csharp/io/swagger/Api/PetApi.cs | 204 +++++++++--------- .../main/csharp/io/swagger/Api/StoreApi.cs | 100 ++++----- .../src/main/csharp/io/swagger/Api/UserApi.cs | 194 +++++++++-------- .../csharp/io/swagger/client/ApiInvoker.cs | 58 ++++- 6 files changed, 380 insertions(+), 271 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/csharp/api.mustache b/modules/swagger-codegen/src/main/resources/csharp/api.mustache index f7cc79c5255..ee3f326c746 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/api.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/api.mustache @@ -10,12 +10,12 @@ namespace {{package}} { {{#operations}} public class {{classname}} { string basePath; - protected RestClient restClient; + public ApiInvoker apiClient {get; set;} public {{classname}}(String basePath = "{{basePath}}") { this.basePath = basePath; - this.restClient = new RestClient(basePath); + this.apiClient = new ApiInvoker(basePath); } /// @@ -45,37 +45,38 @@ namespace {{package}} { /// {{#returnType}}{{{returnType}}}{{/returnType}} public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { - var _request = new RestRequest("{{path}}", Method.{{httpMethod}}); - {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}"); {{/required}}{{/allParams}} - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default - {{#pathParams}}_request.AddUrlSegment("{{baseName}}", ApiInvoker.ParameterToString({{{paramName}}})); // path (url segment) parameter + var path = "{{path}}"; + path = path.Replace("{format}", "json"); + {{#pathParams}}path = path.Replace("{" + "{{baseName}}" + "}", apiClient.ParameterToString({{{paramName}}})); {{/pathParams}} - {{#queryParams}} if ({{paramName}} != null) _request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // query parameter + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + + {{#queryParams}} if ({{paramName}} != null) queryParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // query parameter {{/queryParams}} - {{#headerParams}} if ({{paramName}} != null) _request.AddHeader("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // header parameter + {{#headerParams}} if ({{paramName}} != null) headerParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // header parameter {{/headerParams}} - {{#formParams}}if ({{paramName}} != null) {{#isFile}}_request.AddFile("{{baseName}}", {{paramName}});{{/isFile}}{{^isFile}}_request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // form parameter{{/isFile}} + {{#formParams}}if ({{paramName}} != null) {{#isFile}}fileParams.Add("{{baseName}}", {{paramName}});{{/isFile}}{{^isFile}}formParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // form parameter{{/isFile}} {{/formParams}} - {{#bodyParam}}_request.AddParameter("application/json", ApiInvoker.Serialize({{paramName}}), ParameterType.RequestBody); // http body (model) parameter + {{#bodyParam}}postBody = apiClient.Serialize({{paramName}}); // http body (model) parameter {{/bodyParam}} // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("{{path}}", Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content); } - {{#returnType}}return ({{{returnType}}}) ApiInvoker.Deserialize(response.Content, typeof({{{returnType}}}));{{/returnType}}{{^returnType}} + {{#returnType}}return ({{{returnType}}}) apiClient.Deserialize(response.Content, typeof({{{returnType}}}));{{/returnType}}{{^returnType}} return;{{/returnType}} } {{/operation}} diff --git a/modules/swagger-codegen/src/main/resources/csharp/apiInvoker.mustache b/modules/swagger-codegen/src/main/resources/csharp/apiInvoker.mustache index 9760e44d81a..01406a8add0 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/apiInvoker.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/apiInvoker.mustache @@ -5,10 +5,54 @@ using System.Linq; using System.Net; using System.Text; using Newtonsoft.Json; +using RestSharp; namespace {{invokerPackage}} { public class ApiInvoker { - private static Dictionary defaultHeaderMap = new Dictionary(); + public ApiInvoker() { + this.basePath = "{{basePath}}"; + } + + public ApiInvoker(String basePath) { + this.basePath = basePath; + } + + public string basePath { get; set; } + public RestClient restClient { get; set; } + private Dictionary defaultHeaderMap = new Dictionary(); + + public Object CallApi(String Path, RestSharp.Method Method, Dictionary QueryParams, String PostBody, + Dictionary HeaderParams, Dictionary FormParams, Dictionary FileParams) { + + var request = new RestRequest(Path, Method); + + // add default header, if any + foreach(KeyValuePair defaultHeader in this.defaultHeaderMap) + request.AddHeader(defaultHeader.Key, defaultHeader.Value); + + // add header parameter, if any + foreach(KeyValuePair param in HeaderParams) + request.AddHeader(param.Key, param.Value); + + // add query parameter, if any + foreach(KeyValuePair param in QueryParams) + request.AddUrlSegment(param.Key, param.Value); + + // add form parameter, if any + foreach(KeyValuePair param in FormParams) + request.AddParameter(param.Key, param.Value); + + // add file parameter, if any + foreach(KeyValuePair param in FormParams) + request.AddFile(param.Key, param.Value); + + if (PostBody == null) { + request.AddParameter("application/json", PostBody, ParameterType.RequestBody); // http body (model) parameter + } + + return (Object)restClient.Execute(request); + + } /// /// Add default header @@ -16,7 +60,7 @@ namespace {{invokerPackage}} { /// Header field name /// Header field value /// - public static void AddDefaultHeader(string key, string value) { + public void AddDefaultHeader(string key, string value) { defaultHeaderMap.Add(key, value); } @@ -24,7 +68,7 @@ namespace {{invokerPackage}} { /// Get default header /// /// Dictionary of default header - public static Dictionary GetDefaultHeader() { + public Dictionary GetDefaultHeader() { return defaultHeaderMap; } @@ -33,7 +77,7 @@ namespace {{invokerPackage}} { /// /// String to be escaped /// Escaped string - public static string EscapeString(string str) { + public string EscapeString(string str) { return str; } @@ -42,7 +86,7 @@ namespace {{invokerPackage}} { /// /// The parameter (header, path, query, form) /// Formatted string - public static string ParameterToString(object obj) + public string ParameterToString(object obj) { return (obj is DateTime) ? ((DateTime)obj).ToString ("u") : Convert.ToString (obj); } @@ -53,7 +97,7 @@ namespace {{invokerPackage}} { /// JSON string /// Object type /// Object representation of the JSON string - public static object Deserialize(string content, Type type) { + public object Deserialize(string content, Type type) { if (type.GetType() == typeof(Object)) return (Object)content; @@ -71,7 +115,7 @@ namespace {{invokerPackage}} { /// /// Object /// JSON string - public static string Serialize(object obj) { + public string Serialize(object obj) { try { return obj != null ? JsonConvert.SerializeObject(obj) : null; diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs index 6a39ce7ba75..054cb1bc204 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs @@ -8,12 +8,12 @@ namespace IO.Swagger.Api { public class PetApi { string basePath; - protected RestClient restClient; + public ApiInvoker apiClient {get; set;} public PetApi(String basePath = "http://petstore.swagger.io/v2") { this.basePath = basePath; - this.restClient = new RestClient(basePath); + this.apiClient = new ApiInvoker(basePath); } /// @@ -42,26 +42,27 @@ namespace IO.Swagger.Api { /// public void UpdatePet (Pet Body) { - var _request = new RestRequest("/pet", Method.PUT); - - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } + var path = "/pet"; + path = path.Replace("{format}", "json"); + + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; - _request.AddUrlSegment("format", "json"); // set format to json by default - - _request.AddParameter("application/json", ApiInvoker.Serialize(Body), ParameterType.RequestBody); // http body (model) parameter + postBody = apiClient.Serialize(Body); // http body (model) parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/pet", Method.PUT, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UpdatePet: " + response.Content); } @@ -77,26 +78,27 @@ namespace IO.Swagger.Api { /// public void AddPet (Pet Body) { - var _request = new RestRequest("/pet", Method.POST); - - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } + var path = "/pet"; + path = path.Replace("{format}", "json"); + + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; - _request.AddUrlSegment("format", "json"); // set format to json by default - - _request.AddParameter("application/json", ApiInvoker.Serialize(Body), ParameterType.RequestBody); // http body (model) parameter + postBody = apiClient.Serialize(Body); // http body (model) parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/pet", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling AddPet: " + response.Content); } @@ -112,30 +114,31 @@ namespace IO.Swagger.Api { /// List public List FindPetsByStatus (List Status) { - var _request = new RestRequest("/pet/findByStatus", Method.GET); - - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default + var path = "/pet/findByStatus"; + path = path.Replace("{format}", "json"); - if (Status != null) _request.AddParameter("status", ApiInvoker.ParameterToString(Status)); // query parameter + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + + if (Status != null) queryParams.Add("status", apiClient.ParameterToString(Status)); // query parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/findByStatus", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling FindPetsByStatus: " + response.Content); } - return (List) ApiInvoker.Deserialize(response.Content, typeof(List)); + return (List) apiClient.Deserialize(response.Content, typeof(List)); } @@ -146,30 +149,31 @@ namespace IO.Swagger.Api { /// List public List FindPetsByTags (List Tags) { - var _request = new RestRequest("/pet/findByTags", Method.GET); - - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default + var path = "/pet/findByTags"; + path = path.Replace("{format}", "json"); - if (Tags != null) _request.AddParameter("tags", ApiInvoker.ParameterToString(Tags)); // query parameter + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + + if (Tags != null) queryParams.Add("tags", apiClient.ParameterToString(Tags)); // query parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/findByTags", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling FindPetsByTags: " + response.Content); } - return (List) ApiInvoker.Deserialize(response.Content, typeof(List)); + return (List) apiClient.Deserialize(response.Content, typeof(List)); } @@ -180,33 +184,34 @@ namespace IO.Swagger.Api { /// Pet public Pet GetPetById (long? PetId) { - var _request = new RestRequest("/pet/{petId}", Method.GET); - // verify the required parameter 'PetId' is set if (PetId == null) throw new ApiException(400, "Missing required parameter 'PetId' when calling GetPetById"); - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default - _request.AddUrlSegment("petId", ApiInvoker.ParameterToString(PetId)); // path (url segment) parameter + var path = "/pet/{petId}"; + path = path.Replace("{format}", "json"); + path = path.Replace("{" + "petId" + "}", apiClient.ParameterToString(PetId)); + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/{petId}", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetPetById: " + response.Content); } - return (Pet) ApiInvoker.Deserialize(response.Content, typeof(Pet)); + return (Pet) apiClient.Deserialize(response.Content, typeof(Pet)); } @@ -219,31 +224,32 @@ namespace IO.Swagger.Api { /// public void UpdatePetWithForm (string PetId, string Name, string Status) { - var _request = new RestRequest("/pet/{petId}", Method.POST); - // verify the required parameter 'PetId' is set if (PetId == null) throw new ApiException(400, "Missing required parameter 'PetId' when calling UpdatePetWithForm"); - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } + var path = "/pet/{petId}"; + path = path.Replace("{format}", "json"); + path = path.Replace("{" + "petId" + "}", apiClient.ParameterToString(PetId)); + + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; - _request.AddUrlSegment("format", "json"); // set format to json by default - _request.AddUrlSegment("petId", ApiInvoker.ParameterToString(PetId)); // path (url segment) parameter - - if (Name != null) _request.AddParameter("name", ApiInvoker.ParameterToString(Name)); // form parameter - if (Status != null) _request.AddParameter("status", ApiInvoker.ParameterToString(Status)); // form parameter + if (Name != null) formParams.Add("name", apiClient.ParameterToString(Name)); // form parameter + if (Status != null) formParams.Add("status", apiClient.ParameterToString(Status)); // form parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/{petId}", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UpdatePetWithForm: " + response.Content); } @@ -260,30 +266,31 @@ namespace IO.Swagger.Api { /// public void DeletePet (string ApiKey, long? PetId) { - var _request = new RestRequest("/pet/{petId}", Method.DELETE); - // verify the required parameter 'PetId' is set if (PetId == null) throw new ApiException(400, "Missing required parameter 'PetId' when calling DeletePet"); - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } + var path = "/pet/{petId}"; + path = path.Replace("{format}", "json"); + path = path.Replace("{" + "petId" + "}", apiClient.ParameterToString(PetId)); + + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; - _request.AddUrlSegment("format", "json"); // set format to json by default - _request.AddUrlSegment("petId", ApiInvoker.ParameterToString(PetId)); // path (url segment) parameter - - if (ApiKey != null) _request.AddHeader("api_key", ApiInvoker.ParameterToString(ApiKey)); // header parameter + if (ApiKey != null) headerParams.Add("api_key", apiClient.ParameterToString(ApiKey)); // header parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/{petId}", Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling DeletePet: " + response.Content); } @@ -301,31 +308,32 @@ namespace IO.Swagger.Api { /// public void UploadFile (long? PetId, string AdditionalMetadata, string File) { - var _request = new RestRequest("/pet/{petId}/uploadImage", Method.POST); - // verify the required parameter 'PetId' is set if (PetId == null) throw new ApiException(400, "Missing required parameter 'PetId' when calling UploadFile"); - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } + var path = "/pet/{petId}/uploadImage"; + path = path.Replace("{format}", "json"); + path = path.Replace("{" + "petId" + "}", apiClient.ParameterToString(PetId)); + + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; - _request.AddUrlSegment("format", "json"); // set format to json by default - _request.AddUrlSegment("petId", ApiInvoker.ParameterToString(PetId)); // path (url segment) parameter - - if (AdditionalMetadata != null) _request.AddParameter("additionalMetadata", ApiInvoker.ParameterToString(AdditionalMetadata)); // form parameter - if (File != null) _request.AddFile("file", File); + if (AdditionalMetadata != null) formParams.Add("additionalMetadata", apiClient.ParameterToString(AdditionalMetadata)); // form parameter + if (File != null) fileParams.Add("file", File); // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/{petId}/uploadImage", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UploadFile: " + response.Content); } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs index 5b4236c7a77..9d10a095c44 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs @@ -8,12 +8,12 @@ namespace IO.Swagger.Api { public class StoreApi { string basePath; - protected RestClient restClient; + public ApiInvoker apiClient {get; set;} public StoreApi(String basePath = "http://petstore.swagger.io/v2") { this.basePath = basePath; - this.restClient = new RestClient(basePath); + this.apiClient = new ApiInvoker(basePath); } /// @@ -41,29 +41,30 @@ namespace IO.Swagger.Api { /// Dictionary public Dictionary GetInventory () { - var _request = new RestRequest("/store/inventory", Method.GET); - - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default + var path = "/store/inventory"; + path = path.Replace("{format}", "json"); + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/store/inventory", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetInventory: " + response.Content); } - return (Dictionary) ApiInvoker.Deserialize(response.Content, typeof(Dictionary)); + return (Dictionary) apiClient.Deserialize(response.Content, typeof(Dictionary)); } @@ -74,30 +75,31 @@ namespace IO.Swagger.Api { /// Order public Order PlaceOrder (Order Body) { - var _request = new RestRequest("/store/order", Method.POST); - - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } + var path = "/store/order"; + path = path.Replace("{format}", "json"); + + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; - _request.AddUrlSegment("format", "json"); // set format to json by default - - _request.AddParameter("application/json", ApiInvoker.Serialize(Body), ParameterType.RequestBody); // http body (model) parameter + postBody = apiClient.Serialize(Body); // http body (model) parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/store/order", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling PlaceOrder: " + response.Content); } - return (Order) ApiInvoker.Deserialize(response.Content, typeof(Order)); + return (Order) apiClient.Deserialize(response.Content, typeof(Order)); } @@ -108,33 +110,34 @@ namespace IO.Swagger.Api { /// Order public Order GetOrderById (string OrderId) { - var _request = new RestRequest("/store/order/{orderId}", Method.GET); - // verify the required parameter 'OrderId' is set if (OrderId == null) throw new ApiException(400, "Missing required parameter 'OrderId' when calling GetOrderById"); - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default - _request.AddUrlSegment("orderId", ApiInvoker.ParameterToString(OrderId)); // path (url segment) parameter + var path = "/store/order/{orderId}"; + path = path.Replace("{format}", "json"); + path = path.Replace("{" + "orderId" + "}", apiClient.ParameterToString(OrderId)); + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/store/order/{orderId}", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetOrderById: " + response.Content); } - return (Order) ApiInvoker.Deserialize(response.Content, typeof(Order)); + return (Order) apiClient.Deserialize(response.Content, typeof(Order)); } @@ -145,29 +148,30 @@ namespace IO.Swagger.Api { /// public void DeleteOrder (string OrderId) { - var _request = new RestRequest("/store/order/{orderId}", Method.DELETE); - // verify the required parameter 'OrderId' is set if (OrderId == null) throw new ApiException(400, "Missing required parameter 'OrderId' when calling DeleteOrder"); - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default - _request.AddUrlSegment("orderId", ApiInvoker.ParameterToString(OrderId)); // path (url segment) parameter + var path = "/store/order/{orderId}"; + path = path.Replace("{format}", "json"); + path = path.Replace("{" + "orderId" + "}", apiClient.ParameterToString(OrderId)); + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/store/order/{orderId}", Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling DeleteOrder: " + response.Content); } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs index ff8f23a18b2..c225f45496d 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs @@ -8,12 +8,12 @@ namespace IO.Swagger.Api { public class UserApi { string basePath; - protected RestClient restClient; + public ApiInvoker apiClient {get; set;} public UserApi(String basePath = "http://petstore.swagger.io/v2") { this.basePath = basePath; - this.restClient = new RestClient(basePath); + this.apiClient = new ApiInvoker(basePath); } /// @@ -42,26 +42,27 @@ namespace IO.Swagger.Api { /// public void CreateUser (User Body) { - var _request = new RestRequest("/user", Method.POST); - - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } + var path = "/user"; + path = path.Replace("{format}", "json"); + + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; - _request.AddUrlSegment("format", "json"); // set format to json by default - - _request.AddParameter("application/json", ApiInvoker.Serialize(Body), ParameterType.RequestBody); // http body (model) parameter + postBody = apiClient.Serialize(Body); // http body (model) parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/user", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling CreateUser: " + response.Content); } @@ -77,26 +78,27 @@ namespace IO.Swagger.Api { /// public void CreateUsersWithArrayInput (List Body) { - var _request = new RestRequest("/user/createWithArray", Method.POST); - - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } + var path = "/user/createWithArray"; + path = path.Replace("{format}", "json"); + + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; - _request.AddUrlSegment("format", "json"); // set format to json by default - - _request.AddParameter("application/json", ApiInvoker.Serialize(Body), ParameterType.RequestBody); // http body (model) parameter + postBody = apiClient.Serialize(Body); // http body (model) parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/user/createWithArray", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling CreateUsersWithArrayInput: " + response.Content); } @@ -112,26 +114,27 @@ namespace IO.Swagger.Api { /// public void CreateUsersWithListInput (List Body) { - var _request = new RestRequest("/user/createWithList", Method.POST); - - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } + var path = "/user/createWithList"; + path = path.Replace("{format}", "json"); + + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; - _request.AddUrlSegment("format", "json"); // set format to json by default - - _request.AddParameter("application/json", ApiInvoker.Serialize(Body), ParameterType.RequestBody); // http body (model) parameter + postBody = apiClient.Serialize(Body); // http body (model) parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/user/createWithList", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling CreateUsersWithListInput: " + response.Content); } @@ -148,31 +151,32 @@ namespace IO.Swagger.Api { /// string public string LoginUser (string Username, string Password) { - var _request = new RestRequest("/user/login", Method.GET); - - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default + var path = "/user/login"; + path = path.Replace("{format}", "json"); - if (Username != null) _request.AddParameter("username", ApiInvoker.ParameterToString(Username)); // query parameter - if (Password != null) _request.AddParameter("password", ApiInvoker.ParameterToString(Password)); // query parameter + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + + if (Username != null) queryParams.Add("username", apiClient.ParameterToString(Username)); // query parameter + if (Password != null) queryParams.Add("password", apiClient.ParameterToString(Password)); // query parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/user/login", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling LoginUser: " + response.Content); } - return (string) ApiInvoker.Deserialize(response.Content, typeof(string)); + return (string) apiClient.Deserialize(response.Content, typeof(string)); } @@ -182,25 +186,26 @@ namespace IO.Swagger.Api { /// public void LogoutUser () { - var _request = new RestRequest("/user/logout", Method.GET); - - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default + var path = "/user/logout"; + path = path.Replace("{format}", "json"); + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/user/logout", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling LogoutUser: " + response.Content); } @@ -216,33 +221,34 @@ namespace IO.Swagger.Api { /// User public User GetUserByName (string Username) { - var _request = new RestRequest("/user/{username}", Method.GET); - // verify the required parameter 'Username' is set if (Username == null) throw new ApiException(400, "Missing required parameter 'Username' when calling GetUserByName"); - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default - _request.AddUrlSegment("username", ApiInvoker.ParameterToString(Username)); // path (url segment) parameter + var path = "/user/{username}"; + path = path.Replace("{format}", "json"); + path = path.Replace("{" + "username" + "}", apiClient.ParameterToString(Username)); + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/user/{username}", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetUserByName: " + response.Content); } - return (User) ApiInvoker.Deserialize(response.Content, typeof(User)); + return (User) apiClient.Deserialize(response.Content, typeof(User)); } @@ -254,30 +260,31 @@ namespace IO.Swagger.Api { /// public void UpdateUser (string Username, User Body) { - var _request = new RestRequest("/user/{username}", Method.PUT); - // verify the required parameter 'Username' is set if (Username == null) throw new ApiException(400, "Missing required parameter 'Username' when calling UpdateUser"); - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } + var path = "/user/{username}"; + path = path.Replace("{format}", "json"); + path = path.Replace("{" + "username" + "}", apiClient.ParameterToString(Username)); + + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; - _request.AddUrlSegment("format", "json"); // set format to json by default - _request.AddUrlSegment("username", ApiInvoker.ParameterToString(Username)); // path (url segment) parameter - - _request.AddParameter("application/json", ApiInvoker.Serialize(Body), ParameterType.RequestBody); // http body (model) parameter + postBody = apiClient.Serialize(Body); // http body (model) parameter // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/user/{username}", Method.PUT, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UpdateUser: " + response.Content); } @@ -293,29 +300,30 @@ namespace IO.Swagger.Api { /// public void DeleteUser (string Username) { - var _request = new RestRequest("/user/{username}", Method.DELETE); - // verify the required parameter 'Username' is set if (Username == null) throw new ApiException(400, "Missing required parameter 'Username' when calling DeleteUser"); - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default - _request.AddUrlSegment("username", ApiInvoker.ParameterToString(Username)); // path (url segment) parameter + var path = "/user/{username}"; + path = path.Replace("{format}", "json"); + path = path.Replace("{" + "username" + "}", apiClient.ParameterToString(Username)); + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + // make the HTTP request - IRestResponse response = restClient.Execute(_request); + IRestResponse response = (IRestResponse) apiClient.CallApi("/user/{username}", Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); + if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling DeleteUser: " + response.Content); } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiInvoker.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiInvoker.cs index 8bb36472835..ce5cf0263eb 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiInvoker.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiInvoker.cs @@ -5,10 +5,54 @@ using System.Linq; using System.Net; using System.Text; using Newtonsoft.Json; +using RestSharp; namespace IO.Swagger.Client { public class ApiInvoker { - private static Dictionary defaultHeaderMap = new Dictionary(); + public ApiInvoker() { + this.basePath = "http://petstore.swagger.io/v2"; + } + + public ApiInvoker(String basePath) { + this.basePath = basePath; + } + + public string basePath { get; set; } + public RestClient restClient { get; set; } + private Dictionary defaultHeaderMap = new Dictionary(); + + public Object CallApi(String Path, RestSharp.Method Method, Dictionary QueryParams, String PostBody, + Dictionary HeaderParams, Dictionary FormParams, Dictionary FileParams) { + + var request = new RestRequest(Path, Method); + + // add default header, if any + foreach(KeyValuePair defaultHeader in this.defaultHeaderMap) + request.AddHeader(defaultHeader.Key, defaultHeader.Value); + + // add header parameter, if any + foreach(KeyValuePair param in HeaderParams) + request.AddHeader(param.Key, param.Value); + + // add query parameter, if any + foreach(KeyValuePair param in QueryParams) + request.AddUrlSegment(param.Key, param.Value); + + // add form parameter, if any + foreach(KeyValuePair param in FormParams) + request.AddParameter(param.Key, param.Value); + + // add file parameter, if any + foreach(KeyValuePair param in FormParams) + request.AddFile(param.Key, param.Value); + + if (PostBody == null) { + request.AddParameter("application/json", PostBody, ParameterType.RequestBody); // http body (model) parameter + } + + return (Object)restClient.Execute(request); + + } /// /// Add default header @@ -16,7 +60,7 @@ namespace IO.Swagger.Client { /// Header field name /// Header field value /// - public static void AddDefaultHeader(string key, string value) { + public void AddDefaultHeader(string key, string value) { defaultHeaderMap.Add(key, value); } @@ -24,7 +68,7 @@ namespace IO.Swagger.Client { /// Get default header /// /// Dictionary of default header - public static Dictionary GetDefaultHeader() { + public Dictionary GetDefaultHeader() { return defaultHeaderMap; } @@ -33,7 +77,7 @@ namespace IO.Swagger.Client { /// /// String to be escaped /// Escaped string - public static string EscapeString(string str) { + public string EscapeString(string str) { return str; } @@ -42,7 +86,7 @@ namespace IO.Swagger.Client { /// /// The parameter (header, path, query, form) /// Formatted string - public static string ParameterToString(object obj) + public string ParameterToString(object obj) { return (obj is DateTime) ? ((DateTime)obj).ToString ("u") : Convert.ToString (obj); } @@ -53,7 +97,7 @@ namespace IO.Swagger.Client { /// JSON string /// Object type /// Object representation of the JSON string - public static object Deserialize(string content, Type type) { + public object Deserialize(string content, Type type) { if (type.GetType() == typeof(Object)) return (Object)content; @@ -71,7 +115,7 @@ namespace IO.Swagger.Client { /// /// Object /// JSON string - public static string Serialize(object obj) { + public string Serialize(object obj) { try { return obj != null ? JsonConvert.SerializeObject(obj) : null; From c2c43bba3723ed00628e8ad3dec69c9037f7d71a Mon Sep 17 00:00:00 2001 From: wing328 Date: Tue, 26 May 2015 17:48:52 +0800 Subject: [PATCH 05/72] make datetime nullable --- .../swagger/codegen/languages/CSharpClientCodegen.java | 10 ++++++---- .../csharp/src/main/csharp/io/swagger/Model/Order.cs | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java index da67bb75785..a2463c8a10b 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java @@ -60,7 +60,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig "byte[]", "List", "Dictionary", - "DateTime", + "DateTime?", "String", "Boolean", "Double", @@ -80,9 +80,11 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig typeMapping.put("long", "long?"); typeMapping.put("double", "double?"); typeMapping.put("number", "double?"); - typeMapping.put("Date", "DateTime"); + typeMapping.put("datetime", "DateTime?"); + typeMapping.put("date", "DateTime?"); typeMapping.put("file", "string"); // path to file typeMapping.put("array", "List"); + typeMapping.put("list", "List"); typeMapping.put("map", "Dictionary"); typeMapping.put("object", "Object"); @@ -166,8 +168,8 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig public String getSwaggerType(Property p) { String swaggerType = super.getSwaggerType(p); String type = null; - if(typeMapping.containsKey(swaggerType)) { - type = typeMapping.get(swaggerType); + if(typeMapping.containsKey(swaggerType.toLowerCase())) { + type = typeMapping.get(swaggerType.toLowerCase()); if(languageSpecificPrimitives.contains(type)) return type; } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs index cf773a7a150..a387133dfff 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs @@ -25,7 +25,7 @@ namespace IO.Swagger.Model { [DataMember(Name="shipDate", EmitDefaultValue=false)] - public DateTime ShipDate { get; set; } + public DateTime? ShipDate { get; set; } /* Order Status */ From ca145297e9825f05d0be23679a384569bf707d00 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 26 May 2015 18:00:45 +0800 Subject: [PATCH 06/72] Updated ApiClient of objc sdk. When create api instance, if we don't pass the `apiClient` parameter, then get api client instance from the pool. --- .../src/main/resources/objc/SWGApiClient.m | 10 ++- .../src/main/resources/objc/api-body.mustache | 43 +++++++---- .../main/resources/objc/api-header.mustache | 5 +- .../apiBodyResponseWithContainer.mustache | 4 +- .../objc/apiNonPrimitiveResponse.mustache | 2 +- .../objc/apiPrimitiveResponse.mustache | 6 +- .../main/resources/objc/voidResponse.mustache | 2 +- .../PetstoreClientTests/PetApiTest.m | 10 +++ .../petstore/objc/client/SWGApiClient.m | 10 ++- .../client/petstore/objc/client/SWGPetApi.h | 6 +- .../client/petstore/objc/client/SWGPetApi.m | 75 ++++++++++--------- .../client/petstore/objc/client/SWGStoreApi.h | 5 +- .../client/petstore/objc/client/SWGStoreApi.m | 58 ++++++++------ .../client/petstore/objc/client/SWGUserApi.h | 5 +- .../client/petstore/objc/client/SWGUserApi.m | 74 +++++++++--------- 15 files changed, 186 insertions(+), 129 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m index 15dbee07459..b38b02e0e03 100644 --- a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m +++ b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m @@ -134,10 +134,12 @@ static bool loggingEnabled = true; } +(NSNumber*) nextRequestId { - long nextId = ++requestId; - if(loggingEnabled) - NSLog(@"got id %ld", nextId); - return [NSNumber numberWithLong:nextId]; + @synchronized(self) { + long nextId = ++requestId; + if(loggingEnabled) + NSLog(@"got id %ld", nextId); + return [NSNumber numberWithLong:nextId]; + } } +(NSNumber*) queueRequest { diff --git a/modules/swagger-codegen/src/main/resources/objc/api-body.mustache b/modules/swagger-codegen/src/main/resources/objc/api-body.mustache index b18790e3b6f..abe4376d1ac 100644 --- a/modules/swagger-codegen/src/main/resources/objc/api-body.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/api-body.mustache @@ -2,7 +2,6 @@ #import "{{classname}}.h" #import "SWGFile.h" #import "SWGQueryParamCollection.h" -#import "SWGApiClient.h" {{#imports}}#import "{{import}}.h" {{/imports}} {{newline}} @@ -12,8 +11,34 @@ @end @implementation {{classname}} + static NSString * basePath = @"{{basePath}}"; +#pragma mark - Initialize methods + +- (id) init { + self = [super init]; + if (self) { + self.apiClient = [SWGApiClient sharedClientFromPool:basePath]; + self.defaultHeaders = [NSMutableDictionary dictionary]; + } + return self; +} + +- (id) initWithApiClient:(SWGApiClient *)apiClient { + self = [super init]; + if (self) { + if (apiClient) { + self.apiClient = apiClient; + } + else { + self.apiClient = [SWGApiClient sharedClientFromPool:basePath]; + } + self.defaultHeaders = [NSMutableDictionary dictionary]; + } + return self; +} + +({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static {{classname}}* singletonAPI = nil; @@ -32,21 +57,10 @@ static NSString * basePath = @"{{basePath}}"; return basePath; } --(SWGApiClient*) apiClient { - return [SWGApiClient sharedClientFromPool:basePath]; -} - -(void) addHeader:(NSString*)value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; } --(id) init { - self = [super init]; - self.defaultHeaders = [NSMutableDictionary dictionary]; - [self apiClient]; - return self; -} - -(void) setHeaderValue:(NSString*) value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; @@ -177,8 +191,6 @@ static NSString * basePath = @"{{basePath}}"; {{/requiredParams}} {{/requiredParamCount}} - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - {{#returnContainer}} // response is in a container {{>apiBodyResponseWithContainer}}{{/returnContainer}} @@ -206,3 +218,6 @@ static NSString * basePath = @"{{basePath}}"; {{newline}} {{/operations}} @end + + + diff --git a/modules/swagger-codegen/src/main/resources/objc/api-header.mustache b/modules/swagger-codegen/src/main/resources/objc/api-header.mustache index 0cdccf1b39b..4d571f756ce 100644 --- a/modules/swagger-codegen/src/main/resources/objc/api-header.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/api-header.mustache @@ -2,11 +2,14 @@ {{#imports}}#import "{{import}}.h" {{/imports}} #import "SWGObject.h" +#import "SWGApiClient.h" {{newline}} {{#operations}} @interface {{classname}}: NSObject +@property(nonatomic, assign)SWGApiClient *apiClient; + -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; @@ -34,4 +37,4 @@ {{/operation}} {{/operations}} -@end \ No newline at end of file +@end diff --git a/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache b/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache index 9a53eb2fa06..5aabef86841 100644 --- a/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache @@ -1,5 +1,5 @@ // {{returnContainer}} container response type - return [client dictionary: requestUrl + return [self.apiClient dictionary: requestUrl method: @"{{httpMethod}}" queryParams: queryParams body: bodyDictionary @@ -34,4 +34,4 @@ {{/returnBaseType}} {{/isListContainer}} }]; - \ No newline at end of file + diff --git a/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache b/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache index ff2dcba7a47..81cf1343e53 100644 --- a/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache @@ -1,6 +1,6 @@ {{^returnTypeIsPrimitive}} // comples response type - return [client dictionary: requestUrl + return [self.apiClient dictionary: requestUrl method: @"{{httpMethod}}" queryParams: queryParams body: bodyDictionary diff --git a/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache b/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache index 8e6588c456e..3d6b105f227 100644 --- a/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache @@ -1,5 +1,5 @@ // primitive response type - {{#returnBaseType}}return [client stringWithCompletionBlock: requestUrl + {{#returnBaseType}}return [self.apiClient stringWithCompletionBlock: requestUrl method: @"{{httpMethod}}" queryParams: queryParams body: bodyDictionary @@ -17,7 +17,7 @@ {{/returnBaseType}} {{^returnBaseType}} // no return base type - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"{{httpMethod}}" queryParams: queryParams body: bodyDictionary @@ -32,4 +32,4 @@ completionBlock(nil); }]; {{/returnBaseType}} - \ No newline at end of file + diff --git a/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache b/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache index b128bfd21cc..ab4062a6dbe 100644 --- a/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache @@ -1,4 +1,4 @@ - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"{{httpMethod}}" queryParams: queryParams body: bodyDictionary diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m b/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m index 6fb2b6e57c2..cfc2dc7804f 100644 --- a/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m @@ -12,6 +12,16 @@ [super tearDown]; } +- (void)testCreatePetApi { + SWGPetApi *api1 = [[SWGPetApi alloc] init]; + SWGPetApi *api2 = [[SWGPetApi alloc] init]; + XCTAssertEqual(api1.apiClient, api2.apiClient); + + SWGApiClient *client = [[SWGApiClient alloc] init]; + SWGPetApi *api3 = [[SWGPetApi alloc] initWithApiClient:client]; + XCTAssertNotEqual(api1.apiClient, api3.apiClient); +} + - (void)testCreateAndGetPet { XCTestExpectation *expectation = [self expectationWithDescription:@"testGetPetById"]; SWGPet* pet = [self createPet]; diff --git a/samples/client/petstore/objc/client/SWGApiClient.m b/samples/client/petstore/objc/client/SWGApiClient.m index 15dbee07459..b38b02e0e03 100644 --- a/samples/client/petstore/objc/client/SWGApiClient.m +++ b/samples/client/petstore/objc/client/SWGApiClient.m @@ -134,10 +134,12 @@ static bool loggingEnabled = true; } +(NSNumber*) nextRequestId { - long nextId = ++requestId; - if(loggingEnabled) - NSLog(@"got id %ld", nextId); - return [NSNumber numberWithLong:nextId]; + @synchronized(self) { + long nextId = ++requestId; + if(loggingEnabled) + NSLog(@"got id %ld", nextId); + return [NSNumber numberWithLong:nextId]; + } } +(NSNumber*) queueRequest { diff --git a/samples/client/petstore/objc/client/SWGPetApi.h b/samples/client/petstore/objc/client/SWGPetApi.h index e7a3a84a9f5..aa255cd144e 100644 --- a/samples/client/petstore/objc/client/SWGPetApi.h +++ b/samples/client/petstore/objc/client/SWGPetApi.h @@ -2,10 +2,14 @@ #import "SWGPet.h" #import "SWGFile.h" #import "SWGObject.h" +#import "SWGApiClient.h" @interface SWGPetApi: NSObject +@property(nonatomic, assign)SWGApiClient *apiClient; + +-(instancetype) initWithApiClient:(SWGApiClient *)apiClient; -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +(SWGPetApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; @@ -150,4 +154,4 @@ -@end \ No newline at end of file +@end diff --git a/samples/client/petstore/objc/client/SWGPetApi.m b/samples/client/petstore/objc/client/SWGPetApi.m index 9f2b79c51f8..9487713984b 100644 --- a/samples/client/petstore/objc/client/SWGPetApi.m +++ b/samples/client/petstore/objc/client/SWGPetApi.m @@ -1,7 +1,6 @@ #import "SWGPetApi.h" #import "SWGFile.h" #import "SWGQueryParamCollection.h" -#import "SWGApiClient.h" #import "SWGPet.h" #import "SWGFile.h" @@ -11,8 +10,34 @@ @end @implementation SWGPetApi + static NSString * basePath = @"http://petstore.swagger.io/v2"; +#pragma mark - Initialize methods + +- (id) init { + self = [super init]; + if (self) { + self.apiClient = [SWGApiClient sharedClientFromPool:basePath]; + self.defaultHeaders = [NSMutableDictionary dictionary]; + } + return self; +} + +- (id) initWithApiClient:(SWGApiClient *)apiClient { + self = [super init]; + if (self) { + if (apiClient) { + self.apiClient = apiClient; + } + else { + self.apiClient = [SWGApiClient sharedClientFromPool:basePath]; + } + self.defaultHeaders = [NSMutableDictionary dictionary]; + } + return self; +} + +(SWGPetApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static SWGPetApi* singletonAPI = nil; @@ -31,21 +56,10 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; return basePath; } --(SWGApiClient*) apiClient { - return [SWGApiClient sharedClientFromPool:basePath]; -} - -(void) addHeader:(NSString*)value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; } --(id) init { - self = [super init]; - self.defaultHeaders = [NSMutableDictionary dictionary]; - [self apiClient]; - return self; -} - -(void) setHeaderValue:(NSString*) value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; @@ -135,15 +149,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"PUT" queryParams: queryParams body: bodyDictionary @@ -240,15 +252,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"POST" queryParams: queryParams body: bodyDictionary @@ -328,12 +338,10 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // response is in a container // array container response type - return [client dictionary: requestUrl + return [self.apiClient dictionary: requestUrl method: @"GET" queryParams: queryParams body: bodyDictionary @@ -362,6 +370,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; }]; + @@ -429,12 +438,10 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // response is in a container // array container response type - return [client dictionary: requestUrl + return [self.apiClient dictionary: requestUrl method: @"GET" queryParams: queryParams body: bodyDictionary @@ -463,6 +470,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; }]; + @@ -528,8 +536,6 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - @@ -541,7 +547,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // complex response // comples response type - return [client dictionary: requestUrl + return [self.apiClient dictionary: requestUrl method: @"GET" queryParams: queryParams body: bodyDictionary @@ -648,15 +654,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"POST" queryParams: queryParams body: bodyDictionary @@ -738,15 +742,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"DELETE" queryParams: queryParams body: bodyDictionary @@ -851,15 +853,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"POST" queryParams: queryParams body: bodyDictionary @@ -880,3 +880,6 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; @end + + + diff --git a/samples/client/petstore/objc/client/SWGStoreApi.h b/samples/client/petstore/objc/client/SWGStoreApi.h index b4b8e5af5dc..c2d0dd6b36b 100644 --- a/samples/client/petstore/objc/client/SWGStoreApi.h +++ b/samples/client/petstore/objc/client/SWGStoreApi.h @@ -1,10 +1,13 @@ #import #import "SWGOrder.h" #import "SWGObject.h" +#import "SWGApiClient.h" @interface SWGStoreApi: NSObject +@property(nonatomic, assign)SWGApiClient *apiClient; + -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +(SWGStoreApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; @@ -73,4 +76,4 @@ -@end \ No newline at end of file +@end diff --git a/samples/client/petstore/objc/client/SWGStoreApi.m b/samples/client/petstore/objc/client/SWGStoreApi.m index 75875ff4eae..98b9d9a4eec 100644 --- a/samples/client/petstore/objc/client/SWGStoreApi.m +++ b/samples/client/petstore/objc/client/SWGStoreApi.m @@ -1,7 +1,6 @@ #import "SWGStoreApi.h" #import "SWGFile.h" #import "SWGQueryParamCollection.h" -#import "SWGApiClient.h" #import "SWGOrder.h" @@ -10,8 +9,34 @@ @end @implementation SWGStoreApi + static NSString * basePath = @"http://petstore.swagger.io/v2"; +#pragma mark - Initialize methods + +- (id) init { + self = [super init]; + if (self) { + self.apiClient = [SWGApiClient sharedClientFromPool:basePath]; + self.defaultHeaders = [NSMutableDictionary dictionary]; + } + return self; +} + +- (id) initWithApiClient:(SWGApiClient *)apiClient { + self = [super init]; + if (self) { + if (apiClient) { + self.apiClient = apiClient; + } + else { + self.apiClient = [SWGApiClient sharedClientFromPool:basePath]; + } + self.defaultHeaders = [NSMutableDictionary dictionary]; + } + return self; +} + +(SWGStoreApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static SWGStoreApi* singletonAPI = nil; @@ -30,21 +55,10 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; return basePath; } --(SWGApiClient*) apiClient { - return [SWGApiClient sharedClientFromPool:basePath]; -} - -(void) addHeader:(NSString*)value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; } --(id) init { - self = [super init]; - self.defaultHeaders = [NSMutableDictionary dictionary]; - [self apiClient]; - return self; -} - -(void) setHeaderValue:(NSString*) value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; @@ -109,12 +123,10 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // response is in a container // map container response type - return [client dictionary: requestUrl + return [self.apiClient dictionary: requestUrl method: @"GET" queryParams: queryParams body: bodyDictionary @@ -136,6 +148,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; }]; + @@ -220,8 +233,6 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - @@ -233,7 +244,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // complex response // comples response type - return [client dictionary: requestUrl + return [self.apiClient dictionary: requestUrl method: @"POST" queryParams: queryParams body: bodyDictionary @@ -320,8 +331,6 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - @@ -333,7 +342,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // complex response // comples response type - return [client dictionary: requestUrl + return [self.apiClient dictionary: requestUrl method: @"GET" queryParams: queryParams body: bodyDictionary @@ -420,15 +429,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"DELETE" queryParams: queryParams body: bodyDictionary @@ -449,3 +456,6 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; @end + + + diff --git a/samples/client/petstore/objc/client/SWGUserApi.h b/samples/client/petstore/objc/client/SWGUserApi.h index 47a5dd95e09..d9d5a8abc18 100644 --- a/samples/client/petstore/objc/client/SWGUserApi.h +++ b/samples/client/petstore/objc/client/SWGUserApi.h @@ -1,10 +1,13 @@ #import #import "SWGUser.h" #import "SWGObject.h" +#import "SWGApiClient.h" @interface SWGUserApi: NSObject +@property(nonatomic, assign)SWGApiClient *apiClient; + -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +(SWGUserApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; @@ -141,4 +144,4 @@ -@end \ No newline at end of file +@end diff --git a/samples/client/petstore/objc/client/SWGUserApi.m b/samples/client/petstore/objc/client/SWGUserApi.m index 3e87268a4c6..97a79f01b6d 100644 --- a/samples/client/petstore/objc/client/SWGUserApi.m +++ b/samples/client/petstore/objc/client/SWGUserApi.m @@ -1,7 +1,6 @@ #import "SWGUserApi.h" #import "SWGFile.h" #import "SWGQueryParamCollection.h" -#import "SWGApiClient.h" #import "SWGUser.h" @@ -10,8 +9,34 @@ @end @implementation SWGUserApi + static NSString * basePath = @"http://petstore.swagger.io/v2"; +#pragma mark - Initialize methods + +- (id) init { + self = [super init]; + if (self) { + self.apiClient = [SWGApiClient sharedClientFromPool:basePath]; + self.defaultHeaders = [NSMutableDictionary dictionary]; + } + return self; +} + +- (id) initWithApiClient:(SWGApiClient *)apiClient { + self = [super init]; + if (self) { + if (apiClient) { + self.apiClient = apiClient; + } + else { + self.apiClient = [SWGApiClient sharedClientFromPool:basePath]; + } + self.defaultHeaders = [NSMutableDictionary dictionary]; + } + return self; +} + +(SWGUserApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static SWGUserApi* singletonAPI = nil; @@ -30,21 +55,10 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; return basePath; } --(SWGApiClient*) apiClient { - return [SWGApiClient sharedClientFromPool:basePath]; -} - -(void) addHeader:(NSString*)value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; } --(id) init { - self = [super init]; - self.defaultHeaders = [NSMutableDictionary dictionary]; - [self apiClient]; - return self; -} - -(void) setHeaderValue:(NSString*) value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; @@ -134,15 +148,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"POST" queryParams: queryParams body: bodyDictionary @@ -239,15 +251,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"POST" queryParams: queryParams body: bodyDictionary @@ -344,15 +354,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"POST" queryParams: queryParams body: bodyDictionary @@ -436,8 +444,6 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - @@ -446,7 +452,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // primitive response // primitive response type - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"GET" queryParams: queryParams body: bodyDictionary @@ -465,6 +471,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; + // complex response @@ -528,15 +535,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"GET" queryParams: queryParams body: bodyDictionary @@ -614,8 +619,6 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - @@ -627,7 +630,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // complex response // comples response type - return [client dictionary: requestUrl + return [self.apiClient dictionary: requestUrl method: @"GET" queryParams: queryParams body: bodyDictionary @@ -739,15 +742,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"PUT" queryParams: queryParams body: bodyDictionary @@ -825,15 +826,13 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; - SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath]; - // it's void - return [client stringWithCompletionBlock: requestUrl + return [self.apiClient stringWithCompletionBlock: requestUrl method: @"DELETE" queryParams: queryParams body: bodyDictionary @@ -854,3 +853,6 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; @end + + + From 171bf969c7550cda408e8b20a96630dd330a17b7 Mon Sep 17 00:00:00 2001 From: wing328 Date: Tue, 26 May 2015 23:20:34 +0800 Subject: [PATCH 07/72] add debug switch to configuration --- .../php/SwaggerClient-php/lib/APIClient.php | 20 +++++++++++++++++++ .../SwaggerClient-php/lib/Configuration.php | 3 +++ .../SwaggerClient-php/tests/PetApiTest.php | 3 +++ samples/client/petstore/php/test.php | 3 +++ 4 files changed, 29 insertions(+) diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php index f7002fba18d..bc243e852cb 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php @@ -240,10 +240,30 @@ class APIClient { // Set user agent curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent); + // debugging for curl + if (Configuration::$debug) { + error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, Configuration::$debug_file); + + curl_setopt($curl, CURLOPT_VERBOSE, 1); + try { + $fp = fopen(Configuration::$debug_file, 'w'); + curl_setopt($curl, CURLOPT_STDERR, $fp); + } catch ( \Exception $e ) { + error_log("Exception in enabling curl debug: ".print_r($e, true), 3, Configuration::$debug_file); + } + } else { + curl_setopt($curl, CURLOPT_VERBOSE, 0); + } + // Make the request $response = curl_exec($curl); $response_info = curl_getinfo($curl); + // debug HTTP response body + if (Configuration::$debug) { + error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($response, true)."\n~END~\n", 3, Configuration::$debug_file); + } + // Handle the response if ($response_info['http_code'] == 0) { throw new APIClientException("TIMEOUT: api call to " . $url . diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php index 1f91f8d9063..950b31ed587 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php @@ -34,6 +34,9 @@ class Configuration { // an instance of APIClient public static $apiClient; + public static $debug = false; // by default debugging is disabled + public static $debug_file = 'php://output'; //output debug log to STDOUT by default + /* * manually initalize API client */ diff --git a/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php b/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php index 39c5cecd018..85f0c900a6c 100644 --- a/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php +++ b/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php @@ -7,6 +7,9 @@ class PetApiTest extends \PHPUnit_Framework_TestCase // add a new pet (id 10005) to ensure the pet object is available for all the tests public static function setUpBeforeClass() { + // enable debugging + //SwaggerClient\Configuration::$debug = true; + // skip initializing the API client as it should be automatic //$api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); // new pet diff --git a/samples/client/petstore/php/test.php b/samples/client/petstore/php/test.php index 41c206ee6b0..22bea9db889 100644 --- a/samples/client/petstore/php/test.php +++ b/samples/client/petstore/php/test.php @@ -6,6 +6,9 @@ require_once('SwaggerClient-php/SwaggerClient.php'); //$api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); //$api_client->addDefaultHeader("test1", "value1"); +// to enable logging +//SwaggerClient\Configuration::$debug = true; + $petId = 10005; // ID of pet that needs to be fetched try { //$pet_api = new SwaggerClient\PetAPI($api_client); From 4d1d163a736f4ed22bf33eb0622e0777b27a2d81 Mon Sep 17 00:00:00 2001 From: wing328 Date: Tue, 26 May 2015 23:52:35 +0800 Subject: [PATCH 08/72] update php template to debug curl --- .../src/main/resources/php/APIClient.mustache | 15 +++++++++++++++ .../src/main/resources/php/configuration.mustache | 4 ++++ .../php/SwaggerClient-php/lib/APIClient.php | 7 +------ .../php/SwaggerClient-php/lib/Configuration.php | 1 + samples/client/petstore/php/test.php | 1 + 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache index 70717056b9e..88954ffad3b 100644 --- a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache @@ -235,10 +235,25 @@ class APIClient { // Set user agent curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent); + // debugging for curl + if (Configuration::$debug) { + error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, Configuration::$debug_file); + + curl_setopt($curl, CURLOPT_VERBOSE, 1); + curl_setopt($curl, CURLOPT_STDERR, fopen(Configuration::$debug_file, 'a')); + } else { + curl_setopt($curl, CURLOPT_VERBOSE, 0); + } + // Make the request $response = curl_exec($curl); $response_info = curl_getinfo($curl); + // debug HTTP response body + if (Configuration::$debug) { + error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($response, true)."\n~END~\n", 3, Configuration::$debug_file); + } + // Handle the response if ($response_info['http_code'] == 0) { throw new APIClientException("TIMEOUT: api call to " . $url . diff --git a/modules/swagger-codegen/src/main/resources/php/configuration.mustache b/modules/swagger-codegen/src/main/resources/php/configuration.mustache index 3eaa8dba1f1..5528e8076f3 100644 --- a/modules/swagger-codegen/src/main/resources/php/configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/php/configuration.mustache @@ -34,6 +34,10 @@ class Configuration { // an instance of APIClient public static $apiClient; + // debugging + public static $debug = false; // by default debugging is disabled + public static $debug_file = 'php://output'; //output debug log to STDOUT by default + /* * manually initalize API client */ diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php index bc243e852cb..3e9119003d7 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php @@ -245,12 +245,7 @@ class APIClient { error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, Configuration::$debug_file); curl_setopt($curl, CURLOPT_VERBOSE, 1); - try { - $fp = fopen(Configuration::$debug_file, 'w'); - curl_setopt($curl, CURLOPT_STDERR, $fp); - } catch ( \Exception $e ) { - error_log("Exception in enabling curl debug: ".print_r($e, true), 3, Configuration::$debug_file); - } + curl_setopt($curl, CURLOPT_STDERR, fopen(Configuration::$debug_file, 'a')); } else { curl_setopt($curl, CURLOPT_VERBOSE, 0); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php index 950b31ed587..fe4cbc59998 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php @@ -34,6 +34,7 @@ class Configuration { // an instance of APIClient public static $apiClient; + // debugging public static $debug = false; // by default debugging is disabled public static $debug_file = 'php://output'; //output debug log to STDOUT by default diff --git a/samples/client/petstore/php/test.php b/samples/client/petstore/php/test.php index 22bea9db889..4b63c75f472 100644 --- a/samples/client/petstore/php/test.php +++ b/samples/client/petstore/php/test.php @@ -8,6 +8,7 @@ require_once('SwaggerClient-php/SwaggerClient.php'); // to enable logging //SwaggerClient\Configuration::$debug = true; +//SwaggerClient\Configuration::$debug_file = '/var/tmp/php_debug.log'; $petId = 10005; // ID of pet that needs to be fetched try { From f8cafaaee7d6a9ac69de3c2fcc6c7056ae8c8c53 Mon Sep 17 00:00:00 2001 From: hrachya Date: Tue, 26 May 2015 15:49:32 -0700 Subject: [PATCH 09/72] new CliOption class for wrapping org.apache.commons.cli.Option --- .../wordnik/swagger/codegen/CliOption.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java new file mode 100644 index 00000000000..837759b9d2f --- /dev/null +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java @@ -0,0 +1,44 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wordnik.swagger.codegen; + +import org.apache.commons.cli.Option; + +public class CliOption extends Option { + + private Boolean langSpecific = false; + + public CliOption(String opt, String description) throws IllegalArgumentException { + super(opt, description); + } + + public CliOption(String opt, boolean hasArg, String description) throws IllegalArgumentException { + super(opt, hasArg, description); + } + + public CliOption(String opt, String longOpt, boolean hasArg, String description) throws IllegalArgumentException { + super(opt, longOpt, hasArg, description); + } + + public CliOption(String opt, String description, Boolean langSpecific) throws IllegalArgumentException { + this(opt, description); + this.langSpecific = langSpecific; + } + + public CliOption(String opt, boolean hasArg, String description, Boolean langSpecific) throws IllegalArgumentException { + this(opt, hasArg, description); + this.langSpecific = langSpecific; + } + + public CliOption(String opt, String longOpt, boolean hasArg, String description, Boolean langSpecific) throws IllegalArgumentException { + this(opt, longOpt, hasArg, description); + this.langSpecific = langSpecific; + } + + public Boolean isLangSpecific() { + return langSpecific; + } +} From 9f1504062af24a7a589f2e5112a5ed9356e88881 Mon Sep 17 00:00:00 2001 From: hrachya Date: Tue, 26 May 2015 15:52:25 -0700 Subject: [PATCH 10/72] add List cliOptions() method to CodegenConfig interface with default implementation in DefaultCodegen --- .../main/java/com/wordnik/swagger/codegen/CodegenConfig.java | 1 + .../java/com/wordnik/swagger/codegen/DefaultCodegen.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CodegenConfig.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CodegenConfig.java index 167610fcd70..b112923b6d7 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CodegenConfig.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CodegenConfig.java @@ -27,6 +27,7 @@ public interface CodegenConfig { String getTypeDeclaration(Property p); String getTypeDeclaration(String name); void processOpts(); + List cliOptions(); String generateExamplePath(String path, Operation operation); Set reservedWords(); diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java index 2513bedfcb9..4bb7940b148 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java @@ -77,6 +77,11 @@ public class DefaultCodegen { protected String templateDir; protected Map additionalProperties = new HashMap(); protected List supportingFiles = new ArrayList(); + protected List cliOptions = new ArrayList(); + + public List cliOptions() { + return cliOptions; + } public void processOpts(){ if(additionalProperties.containsKey("templateDir")) { From 33436d62c3a50d3d5c0f56b938fdf6e2e2f36c7a Mon Sep 17 00:00:00 2001 From: hrachya Date: Tue, 26 May 2015 15:57:01 -0700 Subject: [PATCH 11/72] Get all cliOptions for available codegen configs and add to command line options Add all the specified ones to clientOpts properties --- .../com/wordnik/swagger/codegen/Codegen.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java index efda171ff82..1adcc792a8e 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java @@ -51,6 +51,30 @@ public class Codegen extends DefaultGenerator { options.addOption("d", "debug-info", false, "prints additional info for debugging"); options.addOption("a", "auth", true, "adds authorization headers when fetching the swagger definitions remotely. Pass in a URL-encoded string of name:header with a comma separating multiple values"); + //adding additional options from language specific configs + Option existingOption; + for (Map.Entry configEntry : configs.entrySet()) { + for (CliOption langCliOption : configEntry.getValue().cliOptions()) { + //lang specific option + if (langCliOption.isLangSpecific()) { + //option exists, update description + if (options.hasOption(langCliOption.getOpt())) { + existingOption = options.getOption(langCliOption.getOpt()); + existingOption.setDescription(existingOption.getDescription() + "\n" + configEntry.getKey() + ": " + langCliOption.getDescription()); + } else { + //new option, prepend 'lang: ' to the description and add + langCliOption.setDescription(configEntry.getKey() + ": " + langCliOption.getDescription()); + options.addOption((Option) langCliOption); + } + } else { + //not lang specific, add if not already there + if (!options.hasOption(langCliOption.getOpt())) { + options.addOption((Option) langCliOption); + } + } + } + } + ClientOptInput clientOptInput = new ClientOptInput(); ClientOpts clientOpts = new ClientOpts(); Swagger swagger = null; @@ -92,6 +116,13 @@ public class Codegen extends DefaultGenerator { swagger = new SwaggerParser().read(cmd.getOptionValue("i"), clientOptInput.getAuthorizationValues(), true); if (cmd.hasOption("t")) clientOpts.getProperties().put("templateDir", String.valueOf(cmd.getOptionValue("t"))); + + //add all passed cliOptions to clientOpts.properties + for (CliOption langCliOption : clientOptInput.getConfig().cliOptions()) { + if (cmd.hasOption(langCliOption.getOpt())) { + clientOpts.getProperties().put(langCliOption.getOpt(), String.valueOf(cmd.getOptionValue(langCliOption.getOpt()))); + } + } } catch (Exception e) { usage(options); From d7dec5a43d5047c565247f99bd4cde486b9bdf61 Mon Sep 17 00:00:00 2001 From: hrachya Date: Tue, 26 May 2015 16:02:27 -0700 Subject: [PATCH 12/72] Use new functionality to add 't' as a command line option to set 'templateDir' --- modules/swagger-codegen/nbactions.xml | 46 +++++++++++++++++++ .../com/wordnik/swagger/codegen/Codegen.java | 3 -- .../swagger/codegen/DefaultCodegen.java | 6 ++- 3 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 modules/swagger-codegen/nbactions.xml diff --git a/modules/swagger-codegen/nbactions.xml b/modules/swagger-codegen/nbactions.xml new file mode 100644 index 00000000000..92802c5f44d --- /dev/null +++ b/modules/swagger-codegen/nbactions.xml @@ -0,0 +1,46 @@ + + + + run + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2.1:exec + + + -classpath %classpath ${packageClassName} generate -i http://hyeghsealnxd1.bigfish.lan:83/gamestatus.json -l java -o /home/hrachya/Desktop/codegen/java -t blah + java + + + + debug + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2.1:exec + + + -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath ${packageClassName} generate -i http://hyeghsealnxd1.bigfish.lan:83/gamestatus.json -l java -o /home/hrachya/Desktop/codegen/java -t blah + java + true + + + + profile + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2.1:exec + + + -classpath %classpath ${packageClassName} generate -i http://hyeghsealnxd1.bigfish.lan:83/gamestatus.json -l java -o /home/hrachya/Desktop/codegen/java -t blah + java + + + diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java index 1adcc792a8e..76c95ae102f 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java @@ -47,7 +47,6 @@ public class Codegen extends DefaultGenerator { options.addOption("l", "lang", true, "client language to generate.\nAvailable languages include:\n\t[" + configString + "]"); options.addOption("o", "output", true, "where to write the generated files"); options.addOption("i", "input-spec", true, "location of the swagger spec, as URL or file"); - options.addOption("t", "template-dir", true, "folder containing the template files"); options.addOption("d", "debug-info", false, "prints additional info for debugging"); options.addOption("a", "auth", true, "adds authorization headers when fetching the swagger definitions remotely. Pass in a URL-encoded string of name:header with a comma separating multiple values"); @@ -114,8 +113,6 @@ public class Codegen extends DefaultGenerator { } if (cmd.hasOption("i")) swagger = new SwaggerParser().read(cmd.getOptionValue("i"), clientOptInput.getAuthorizationValues(), true); - if (cmd.hasOption("t")) - clientOpts.getProperties().put("templateDir", String.valueOf(cmd.getOptionValue("t"))); //add all passed cliOptions to clientOpts.properties for (CliOption langCliOption : clientOptInput.getConfig().cliOptions()) { diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java index 4bb7940b148..97c5798f223 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java @@ -84,8 +84,8 @@ public class DefaultCodegen { } public void processOpts(){ - if(additionalProperties.containsKey("templateDir")) { - this.setTemplateDir((String)additionalProperties.get("templateDir")); + if(additionalProperties.containsKey("t")) { + this.setTemplateDir((String)additionalProperties.get("t")); } } @@ -286,6 +286,8 @@ public class DefaultCodegen { importMapping.put("LocalDateTime", "org.joda.time.*"); importMapping.put("LocalDate", "org.joda.time.*"); importMapping.put("LocalTime", "org.joda.time.*"); + + cliOptions.add(new CliOption("t", "template-dir", true, "folder containing the template files")); } From e08a5a9d83aeb979181ef1469ddc13ae90d6b134 Mon Sep 17 00:00:00 2001 From: hrachya Date: Tue, 26 May 2015 17:01:07 -0700 Subject: [PATCH 13/72] Add 'modelPackage' and 'apiPackage' as command line options Add setters for modelPackage and apiPackage --- .../swagger/codegen/DefaultCodegen.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java index 97c5798f223..6571990efc7 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java @@ -87,6 +87,14 @@ public class DefaultCodegen { if(additionalProperties.containsKey("t")) { this.setTemplateDir((String)additionalProperties.get("t")); } + + if(additionalProperties.containsKey("modelPackage")) { + this.setModelPackage((String)additionalProperties.get("modelPackage")); + } + + if(additionalProperties.containsKey("apiPackage")) { + this.setApiPackage((String)additionalProperties.get("apiPackage")); + } } // override with any special post-processing @@ -183,6 +191,14 @@ public class DefaultCodegen { this.templateDir = templateDir; } + public void setModelPackage(String modelPackage) { + this.modelPackage = modelPackage; + } + + public void setApiPackage(String apiPackage) { + this.apiPackage = apiPackage; + } + public String toApiFilename(String name) { return toApiName(name); } @@ -288,6 +304,8 @@ public class DefaultCodegen { importMapping.put("LocalTime", "org.joda.time.*"); cliOptions.add(new CliOption("t", "template-dir", true, "folder containing the template files")); + cliOptions.add(new CliOption("modelPackage", "model-package", true, "Package for generated models")); + cliOptions.add(new CliOption("apiPackage", "api-package", true, "Package for generated api classes")); } From 1e09f5149ee773fd970fce9da6901f0762f880fe Mon Sep 17 00:00:00 2001 From: hrachya Date: Tue, 26 May 2015 17:05:53 -0700 Subject: [PATCH 14/72] Add 'invokerPackage', 'groupId', 'arifactId', 'artifactVersion', 'sourceFolder' command line options for java (and all the derived ones jaxrs, spring-mvc ...) Add processOpts override to process java specific options Move supporting file initialization from constructor to processOpts, since it uses some of the options that are not yet set in the constructor Add setters --- .../codegen/languages/JavaClientCodegen.java | 88 ++++++++++++++++--- 1 file changed, 75 insertions(+), 13 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java index 7c0ac7422ff..622e1322a1d 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java @@ -45,19 +45,6 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { "native", "super", "while") ); - additionalProperties.put("invokerPackage", invokerPackage); - additionalProperties.put("groupId", groupId); - additionalProperties.put("artifactId", artifactId); - additionalProperties.put("artifactVersion", artifactVersion); - - supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); - supportingFiles.add(new SupportingFile("apiInvoker.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.java")); - supportingFiles.add(new SupportingFile("JsonUtil.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java")); - supportingFiles.add(new SupportingFile("apiException.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java")); - languageSpecificPrimitives = new HashSet( Arrays.asList( "String", @@ -71,8 +58,65 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { ); instantiationTypes.put("array", "ArrayList"); instantiationTypes.put("map", "HashMap"); + + cliOptions.add(new CliOption("invokerPackage", "invoker-package", true, "Root package for generated code", true)); + cliOptions.add(new CliOption("groupId", "group-id", true, "groupId in pom.xml", true)); + cliOptions.add(new CliOption("artifactId", "artifact-id", true, "groupId in pom.xml", true)); + cliOptions.add(new CliOption("artifactVersion", "artifact-version", true, "artifact version in pom.xml", true)); + cliOptions.add(new CliOption("sourceFolder", "source-folder", true, "Source folder for generated code", true)); } + @Override + public void processOpts() { + super.processOpts(); + + if(additionalProperties.containsKey("invokerPackage")) { + this.setInvokerPackage((String)additionalProperties.get("invokerPackage")); + } + else{ + //not set, use default to be passed to template + additionalProperties.put("invokerPackage", invokerPackage); + } + + if(additionalProperties.containsKey("groupId")) { + this.setGroupId((String)additionalProperties.get("groupId")); + } + else{ + //not set, use to be passed to template + additionalProperties.put("groupId", groupId); + } + + if(additionalProperties.containsKey("artifactId")) { + this.setArtifactId((String)additionalProperties.get("artifactId")); + } + else{ + //not set, use to be passed to template + additionalProperties.put("artifactId", artifactId); + } + + if(additionalProperties.containsKey("artifactVersion")) { + this.setArtifactVersion((String)additionalProperties.get("artifactVersion")); + } + else{ + //not set, use to be passed to template + additionalProperties.put("artifactVersion", artifactVersion); + } + + if(additionalProperties.containsKey("sourceFolder")) { + this.setSourceFolder((String)additionalProperties.get("sourceFolder")); + } + + supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); + supportingFiles.add(new SupportingFile("apiInvoker.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.java")); + supportingFiles.add(new SupportingFile("JsonUtil.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java")); + supportingFiles.add(new SupportingFile("apiException.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java")); + } + + + @Override public String escapeReservedWord(String name) { return "_" + name; @@ -169,5 +213,23 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { return camelize(operationId, true); } + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } } From 74f5c769f9b5a31ed6980d26ab6940101d6cba81 Mon Sep 17 00:00:00 2001 From: hrachya Date: Tue, 26 May 2015 17:10:19 -0700 Subject: [PATCH 15/72] removing extra file, was committed by mistake --- modules/swagger-codegen/nbactions.xml | 46 --------------------------- 1 file changed, 46 deletions(-) delete mode 100644 modules/swagger-codegen/nbactions.xml diff --git a/modules/swagger-codegen/nbactions.xml b/modules/swagger-codegen/nbactions.xml deleted file mode 100644 index 92802c5f44d..00000000000 --- a/modules/swagger-codegen/nbactions.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - run - - jar - - - process-classes - org.codehaus.mojo:exec-maven-plugin:1.2.1:exec - - - -classpath %classpath ${packageClassName} generate -i http://hyeghsealnxd1.bigfish.lan:83/gamestatus.json -l java -o /home/hrachya/Desktop/codegen/java -t blah - java - - - - debug - - jar - - - process-classes - org.codehaus.mojo:exec-maven-plugin:1.2.1:exec - - - -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath ${packageClassName} generate -i http://hyeghsealnxd1.bigfish.lan:83/gamestatus.json -l java -o /home/hrachya/Desktop/codegen/java -t blah - java - true - - - - profile - - jar - - - process-classes - org.codehaus.mojo:exec-maven-plugin:1.2.1:exec - - - -classpath %classpath ${packageClassName} generate -i http://hyeghsealnxd1.bigfish.lan:83/gamestatus.json -l java -o /home/hrachya/Desktop/codegen/java -t blah - java - - - From 866b546cfde78a9d86fdda65264d0685f26b697b Mon Sep 17 00:00:00 2001 From: wing328 Date: Wed, 27 May 2015 17:56:39 +0800 Subject: [PATCH 16/72] make api client pluggable --- .../codegen/languages/PerlClientCodegen.java | 1 + .../main/resources/perl/APIClient.mustache | 103 ++++++------------ .../resources/perl/Configuration.mustache | 16 +++ .../src/main/resources/perl/api.mustache | 24 ++-- .../perl/lib/WWW/SwaggerClient/APIClient.pm | 103 ++++++------------ .../lib/WWW/SwaggerClient/Configuration.pm | 16 +++ .../perl/lib/WWW/SwaggerClient/PetApi.pm | 81 +++++--------- .../perl/lib/WWW/SwaggerClient/StoreApi.pm | 25 +---- .../perl/lib/WWW/SwaggerClient/UserApi.pm | 55 +++------- samples/client/petstore/perl/t/01_pet_api.t | 9 +- 10 files changed, 166 insertions(+), 267 deletions(-) create mode 100644 modules/swagger-codegen/src/main/resources/perl/Configuration.mustache create mode 100644 samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java index b25e4490e85..8f8ff21bc58 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java @@ -77,6 +77,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("map", "HASH"); supportingFiles.add(new SupportingFile("APIClient.mustache", "lib/WWW/" + invokerPackage, "APIClient.pm")); + supportingFiles.add(new SupportingFile("Configuration.mustache", "lib/WWW/" + invokerPackage, "Configuration.pm")); supportingFiles.add(new SupportingFile("BaseObject.mustache", "lib/WWW/" + invokerPackage, "Object/BaseObject.pm")); } diff --git a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache index 19079a07922..5d5dc0cdb96 100644 --- a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache @@ -15,20 +15,16 @@ use URI::Escape; use Scalar::Util; use Log::Any qw($log); use Carp; -use Switch; use Module::Runtime qw(use_module); -# class variables -my $ua = LWP::UserAgent->new; -my $http_user_agent = 'Perl-Swagger'; # HTTP user-agent -my $http_timeout; #timeout -my $base_url = "{{basePath}}"; - - sub new { my $class = shift; - my %args = @_; + my (%args) = ( + 'ua' => LWP::UserAgent->new, + 'base_url' => '{{basePath}}', + @_ + ); return bless \%args, $class; } @@ -38,8 +34,8 @@ sub new # @param string $user_agent The user agent of the API client # sub set_user_agent { - my $user_agent = shift; - $http_user_agent= $user_agent; + my ($self, $user_agent) = @_; + $self->{http_user_agent}= $user_agent; } # Set timeout @@ -47,11 +43,11 @@ sub set_user_agent { # @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] # sub set_timeout { - my $seconds = shift; + my ($self, $seconds) = @_; if (!looks_like_number($seconds)) { croak('Timeout variable must be numeric.'); } - $http_timeout = $seconds; + $self->{http_timeout} = $seconds; } # make the HTTP request @@ -67,7 +63,7 @@ sub call_api { my $headers = HTTP::Headers->new(%$header_params); - my $_url = $base_url . $resource_path; + my $_url = $self->{base_url} . $resource_path; # build query if (%$query_params) { @@ -80,43 +76,42 @@ sub call_api { # Make the HTTP request my $_request; - switch ($method) { - case 'POST' { + if ($method eq 'POST') { # multipart my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; $_request = POST($_url, Accept => $header_params->{Accept}, Content_Type => $_content_type, Content => $_body_data); - } - case 'PUT' { + } + elsif ($method eq 'PUT') { # multipart my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; $_request = PUT($_url, Accept => $header_params->{Accept}, Content_Type => $_content_type, Content => $_body_data); - } - case 'GET' { + } + elsif ($method eq 'GET') { $_request = GET($_url, Accept => $header_params->{'Accept'}, Content_Type => $header_params->{'Content-Type'}); - } - case 'HEAD' { + } + elsif ($method eq 'HEAD') { $_request = HEAD($_url, Accept => $header_params->{'Accept'}, Content_Type => $header_params->{'Content-Type'}); - } - case 'DELETE' { #TODO support form data + } + elsif ($method eq 'DELETE') { #TODO support form data $_request = DELETE($_url, Accept => $header_params->{'Accept'}, Content_Type => $header_params->{'Content-Type'}, Content => $_body_data); - } - case 'PATCH' { #TODO - } - + } + elsif ($method eq 'PATCH') { #TODO + } + else { } - $ua->timeout($http_timeout); - $ua->agent($http_user_agent); + $self->{ua}->timeout($self->{http_timeout} || $WWW::{{invokerPackage}}::Configuration::http_timeout); + $self->{ua}->agent($self->{http_user_agent} || $WWW::{{invokerPackage}}::Configuration::http_user_agent); - my $_response = $ua->request($_request); + my $_response = $self->{ua}->request($_request); unless ($_response->is_success) { croak("API Exception(".$_response->code."): ".$_response->message); @@ -126,41 +121,13 @@ sub call_api { } - -# Build a JSON POST object -sub sanitize_for_serialization -{ -# my $data = shift; -# if (is_scalar($data) || null === $data) { -# $sanitized = $data; -# } else if ($data instanceof \DateTime) { -# $sanitized = $data->format(\DateTime::ISO8601); -# } else if (is_array($data)) { -# foreach ($data as $property => $value) { -# $data[$property] = $this->sanitizeForSerialization($value); -# } -# $sanitized = $data; -# } else if (is_object($data)) { -# $values = array(); -# foreach (array_keys($data::$swaggerTypes) as $property) { -# $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); -# } -# $sanitized = $values; -# } else { -# $sanitized = (string)$data; -# } -# -# return $sanitized; -} - - # Take value and turn it into a string suitable for inclusion in # the path, by url-encoding. # @param string $value a string which will be part of the path # @return string the serialized object sub to_path_value { - my $value = shift; - return uri_escape(to_string($value)); + my ($self, $value) = @_; + return uri_escape($self->to_string($value)); } @@ -171,11 +138,11 @@ sub to_path_value { # @param object $object an object to be serialized to a string # @return string the serialized object sub to_query_value { - my $object = shift; + my ($self, $object) = @_; if (is_array($object)) { return implode(',', $object); } else { - return toString($object); + return $self->to_string($object); } } @@ -186,8 +153,8 @@ sub to_query_value { # @param string $value a string which will be part of the header # @return string the header string sub to_header_value { - my $value = shift; - return to_string($value); + my ($self, $value) = @_; + return $self->to_string($value); } # Take value and turn it into a string suitable for inclusion in @@ -196,8 +163,8 @@ sub to_header_value { # @param string $value the value of the form parameter # @return string the form string sub to_form_value { - my $value = shift; - return to_string($value); + my ($self, $value) = @_; + return $self->to_string($value); } # Take value and turn it into a string suitable for inclusion in @@ -206,7 +173,7 @@ sub to_form_value { # @param string $value the value of the parameter # @return string the header string sub to_string { - my $value = shift; + my ($self, $value) = @_; if (ref($value) eq "DateTime") { # datetime in ISO8601 format return $value->datetime(); } diff --git a/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache b/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache new file mode 100644 index 00000000000..0967dc136c3 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache @@ -0,0 +1,16 @@ +package WWW::{{invokerPackage}}::Configuration; + +use strict; +use warnings; +use utf8; + +use Log::Any qw($log); +use Carp; + +# class/static variables +my $api_client = WWW::SwaggerClient::APIClient->new; +my $http_timeout = 180; +my $http_user_agent = 'Perl-Swagger'; + + +1; diff --git a/modules/swagger-codegen/src/main/resources/perl/api.mustache b/modules/swagger-codegen/src/main/resources/perl/api.mustache index 131eb3a3934..4996534c35e 100644 --- a/modules/swagger-codegen/src/main/resources/perl/api.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/api.mustache @@ -28,9 +28,6 @@ use Carp qw( croak ); use Log::Any qw($log); -#use WWW::Swagger::Model::Category; -#use WWW::Swagger::Model::Pet; - {{#operations}} use WWW::{{invokerPackage}}::APIClient; @@ -92,37 +89,34 @@ sub new { } $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type({{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}); - {{#queryParams}} # query params + {{#queryParams}}# query params if ( exists $args{'{{paramName}}'}) { - $query_params->{'{{baseName}}'} = WWW::{{invokerPacakge}}::APIClient::to_query_value($args{'{{paramName}}'}); + $query_params->{'{{baseName}}'} = $self->{api_client}->to_query_value($args{'{{paramName}}'}); }{{/queryParams}} - {{#headerParams}} # header params + {{#headerParams}}# header params if ( exists $args{'{{paramName}}'}) { - $header_params->{'{{baseName}}'} = WWW::{{invokerPackage}}::APIClient::to_header_value($args{'{{paramName}}'}); + $header_params->{'{{baseName}}'} = $self->{api_client}->to_header_value($args{'{{paramName}}'}); }{{/headerParams}} - {{#pathParams}} # path params + {{#pathParams}}# path params if ( exists $args{'{{paramName}}'}) { my $_base_variable = "{" . "{{baseName}}" . "}"; - my $_base_value = WWW::{{invokerPackage}}::APIClient::to_path_value($args{'{{paramName}}'}); + my $_base_value = $self->{api_client}->to_path_value($args{'{{paramName}}'}); $_resource_path =~ s/$_base_variable/$_base_value/g; }{{/pathParams}} - {{#formParams}} # form params + {{#formParams}}# form params if ( exists $args{'{{paramName}}'} ) { {{#isFile}}$form_params->{'{{baseName}}'} = [] unless defined $form_params->{'{{baseName}}'}; push $form_params->{'{{baseName}}'}, $args{'{{paramName}}'}; {{/isFile}} - {{^isFile}}$form_params->{'{{baseName}}'} = WWW::{{invokerPackage}}::APIClient::to_form_value($args{'{{paramName}}'}); + {{^isFile}}$form_params->{'{{baseName}}'} = $self->{api_client}->to_form_value($args{'{{paramName}}'}); {{/isFile}} }{{/formParams}} my $_body_data; - {{#bodyParams}} # body params + {{#bodyParams}}# body params if ( exists $args{'{{paramName}}'}) { $_body_data = $args{'{{paramName}}'}; }{{/bodyParams}} - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call {{#returnType}}my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm index 0f0fea793e3..cf4ec0db4f3 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm @@ -15,20 +15,16 @@ use URI::Escape; use Scalar::Util; use Log::Any qw($log); use Carp; -use Switch; use Module::Runtime qw(use_module); -# class variables -my $ua = LWP::UserAgent->new; -my $http_user_agent = 'Perl-Swagger'; # HTTP user-agent -my $http_timeout; #timeout -my $base_url = "http://petstore.swagger.io/v2"; - - sub new { my $class = shift; - my %args = @_; + my (%args) = ( + 'ua' => LWP::UserAgent->new, + 'base_url' => 'http://petstore.swagger.io/v2', + @_ + ); return bless \%args, $class; } @@ -38,8 +34,8 @@ sub new # @param string $user_agent The user agent of the API client # sub set_user_agent { - my $user_agent = shift; - $http_user_agent= $user_agent; + my ($self, $user_agent) = @_; + $self->{http_user_agent}= $user_agent; } # Set timeout @@ -47,11 +43,11 @@ sub set_user_agent { # @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] # sub set_timeout { - my $seconds = shift; + my ($self, $seconds) = @_; if (!looks_like_number($seconds)) { croak('Timeout variable must be numeric.'); } - $http_timeout = $seconds; + $self->{http_timeout} = $seconds; } # make the HTTP request @@ -67,7 +63,7 @@ sub call_api { my $headers = HTTP::Headers->new(%$header_params); - my $_url = $base_url . $resource_path; + my $_url = $self->{base_url} . $resource_path; # build query if (%$query_params) { @@ -80,43 +76,42 @@ sub call_api { # Make the HTTP request my $_request; - switch ($method) { - case 'POST' { + if ($method eq 'POST') { # multipart my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; $_request = POST($_url, Accept => $header_params->{Accept}, Content_Type => $_content_type, Content => $_body_data); - } - case 'PUT' { + } + elsif ($method eq 'PUT') { # multipart my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; $_request = PUT($_url, Accept => $header_params->{Accept}, Content_Type => $_content_type, Content => $_body_data); - } - case 'GET' { + } + elsif ($method eq 'GET') { $_request = GET($_url, Accept => $header_params->{'Accept'}, Content_Type => $header_params->{'Content-Type'}); - } - case 'HEAD' { + } + elsif ($method eq 'HEAD') { $_request = HEAD($_url, Accept => $header_params->{'Accept'}, Content_Type => $header_params->{'Content-Type'}); - } - case 'DELETE' { #TODO support form data + } + elsif ($method eq 'DELETE') { #TODO support form data $_request = DELETE($_url, Accept => $header_params->{'Accept'}, Content_Type => $header_params->{'Content-Type'}, Content => $_body_data); - } - case 'PATCH' { #TODO - } - + } + elsif ($method eq 'PATCH') { #TODO + } + else { } - $ua->timeout($http_timeout); - $ua->agent($http_user_agent); + $self->{ua}->timeout($self->{http_timeout} || $WWW::SwaggerClient::Configuration::http_timeout); + $self->{ua}->agent($self->{http_user_agent} || $WWW::SwaggerClient::Configuration::http_user_agent); - my $_response = $ua->request($_request); + my $_response = $self->{ua}->request($_request); unless ($_response->is_success) { croak("API Exception(".$_response->code."): ".$_response->message); @@ -126,41 +121,13 @@ sub call_api { } - -# Build a JSON POST object -sub sanitize_for_serialization -{ -# my $data = shift; -# if (is_scalar($data) || null === $data) { -# $sanitized = $data; -# } else if ($data instanceof \DateTime) { -# $sanitized = $data->format(\DateTime::ISO8601); -# } else if (is_array($data)) { -# foreach ($data as $property => $value) { -# $data[$property] = $this->sanitizeForSerialization($value); -# } -# $sanitized = $data; -# } else if (is_object($data)) { -# $values = array(); -# foreach (array_keys($data::$swaggerTypes) as $property) { -# $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); -# } -# $sanitized = $values; -# } else { -# $sanitized = (string)$data; -# } -# -# return $sanitized; -} - - # Take value and turn it into a string suitable for inclusion in # the path, by url-encoding. # @param string $value a string which will be part of the path # @return string the serialized object sub to_path_value { - my $value = shift; - return uri_escape(to_string($value)); + my ($self, $value) = @_; + return uri_escape($self->to_string($value)); } @@ -171,11 +138,11 @@ sub to_path_value { # @param object $object an object to be serialized to a string # @return string the serialized object sub to_query_value { - my $object = shift; + my ($self, $object) = @_; if (is_array($object)) { return implode(',', $object); } else { - return toString($object); + return $self->to_string($object); } } @@ -186,8 +153,8 @@ sub to_query_value { # @param string $value a string which will be part of the header # @return string the header string sub to_header_value { - my $value = shift; - return to_string($value); + my ($self, $value) = @_; + return $self->to_string($value); } # Take value and turn it into a string suitable for inclusion in @@ -196,8 +163,8 @@ sub to_header_value { # @param string $value the value of the form parameter # @return string the form string sub to_form_value { - my $value = shift; - return to_string($value); + my ($self, $value) = @_; + return $self->to_string($value); } # Take value and turn it into a string suitable for inclusion in @@ -206,7 +173,7 @@ sub to_form_value { # @param string $value the value of the parameter # @return string the header string sub to_string { - my $value = shift; + my ($self, $value) = @_; if (ref($value) eq "DateTime") { # datetime in ISO8601 format return $value->datetime(); } diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm new file mode 100644 index 00000000000..b8c57e66843 --- /dev/null +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm @@ -0,0 +1,16 @@ +package WWW::SwaggerClient::Configuration; + +use strict; +use warnings; +use utf8; + +use Log::Any qw($log); +use Carp; + +# class/static variables +my $api_client = WWW::SwaggerClient::APIClient->new; +my $http_timeout = 180; +my $http_user_agent = 'Perl-Swagger'; + + +1; diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm index 57237a96974..e796022bad1 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm @@ -28,9 +28,6 @@ use Carp qw( croak ); use Log::Any qw($log); -#use WWW::Swagger::Model::Category; -#use WWW::Swagger::Model::Pet; - use WWW::SwaggerClient::APIClient; @@ -91,21 +88,18 @@ sub new { if ($_header_accept) { $header_params->{'Accept'} = $_header_accept; } - $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type('application/json', 'application/xml', ); + $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type('application/json', 'application/xml'); my $_body_data; - # body params + # body params if ( exists $args{'body'}) { $_body_data = $args{'body'}; } - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, @@ -142,21 +136,18 @@ sub new { if ($_header_accept) { $header_params->{'Accept'} = $_header_accept; } - $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type('application/json', 'application/xml', ); + $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type('application/json', 'application/xml'); my $_body_data; - # body params + # body params if ( exists $args{'body'}) { $_body_data = $args{'body'}; } - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, @@ -195,9 +186,9 @@ sub new { } $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type(); - # query params + # query params if ( exists $args{'status'}) { - $query_params->{'status'} = WWW::::APIClient::to_query_value($args{'status'}); + $query_params->{'status'} = $self->{api_client}->to_query_value($args{'status'}); } @@ -205,9 +196,6 @@ sub new { my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, @@ -249,9 +237,9 @@ sub new { } $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type(); - # query params + # query params if ( exists $args{'tags'}) { - $query_params->{'tags'} = WWW::::APIClient::to_query_value($args{'tags'}); + $query_params->{'tags'} = $self->{api_client}->to_query_value($args{'tags'}); } @@ -259,9 +247,6 @@ sub new { my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, @@ -310,19 +295,16 @@ sub new { - # path params + # path params if ( exists $args{'pet_id'}) { my $_base_variable = "{" . "petId" . "}"; - my $_base_value = WWW::SwaggerClient::APIClient::to_path_value($args{'pet_id'}); + my $_base_value = $self->{api_client}->to_path_value($args{'pet_id'}); $_resource_path =~ s/$_base_variable/$_base_value/g; } my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, @@ -369,33 +351,30 @@ sub new { if ($_header_accept) { $header_params->{'Accept'} = $_header_accept; } - $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type('application/x-www-form-urlencoded', ); + $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type('application/x-www-form-urlencoded'); - # path params + # path params if ( exists $args{'pet_id'}) { my $_base_variable = "{" . "petId" . "}"; - my $_base_value = WWW::SwaggerClient::APIClient::to_path_value($args{'pet_id'}); + my $_base_value = $self->{api_client}->to_path_value($args{'pet_id'}); $_resource_path =~ s/$_base_variable/$_base_value/g; } - # form params + # form params if ( exists $args{'name'} ) { - $form_params->{'name'} = WWW::SwaggerClient::APIClient::to_form_value($args{'name'}); + $form_params->{'name'} = $self->{api_client}->to_form_value($args{'name'}); - } # form params + }# form params if ( exists $args{'status'} ) { - $form_params->{'status'} = WWW::SwaggerClient::APIClient::to_form_value($args{'status'}); + $form_params->{'status'} = $self->{api_client}->to_form_value($args{'status'}); } my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, @@ -441,23 +420,20 @@ sub new { $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type(); - # header params + # header params if ( exists $args{'api_key'}) { - $header_params->{'api_key'} = WWW::SwaggerClient::APIClient::to_header_value($args{'api_key'}); + $header_params->{'api_key'} = $self->{api_client}->to_header_value($args{'api_key'}); } - # path params + # path params if ( exists $args{'pet_id'}) { my $_base_variable = "{" . "petId" . "}"; - my $_base_value = WWW::SwaggerClient::APIClient::to_path_value($args{'pet_id'}); + my $_base_value = $self->{api_client}->to_path_value($args{'pet_id'}); $_resource_path =~ s/$_base_variable/$_base_value/g; } my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, @@ -501,22 +477,22 @@ sub new { if ($_header_accept) { $header_params->{'Accept'} = $_header_accept; } - $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type('multipart/form-data', ); + $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type('multipart/form-data'); - # path params + # path params if ( exists $args{'pet_id'}) { my $_base_variable = "{" . "petId" . "}"; - my $_base_value = WWW::SwaggerClient::APIClient::to_path_value($args{'pet_id'}); + my $_base_value = $self->{api_client}->to_path_value($args{'pet_id'}); $_resource_path =~ s/$_base_variable/$_base_value/g; } - # form params + # form params if ( exists $args{'additional_metadata'} ) { - $form_params->{'additionalMetadata'} = WWW::SwaggerClient::APIClient::to_form_value($args{'additional_metadata'}); + $form_params->{'additionalMetadata'} = $self->{api_client}->to_form_value($args{'additional_metadata'}); - } # form params + }# form params if ( exists $args{'file'} ) { $form_params->{'file'} = [] unless defined $form_params->{'file'}; push $form_params->{'file'}, $args{'file'}; @@ -526,9 +502,6 @@ sub new { my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm index d4261c6bbec..e457c99cac2 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm @@ -28,9 +28,6 @@ use Carp qw( croak ); use Log::Any qw($log); -#use WWW::Swagger::Model::Category; -#use WWW::Swagger::Model::Pet; - use WWW::SwaggerClient::APIClient; @@ -95,9 +92,6 @@ sub new { my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, @@ -144,14 +138,11 @@ sub new { my $_body_data; - # body params + # body params if ( exists $args{'body'}) { $_body_data = $args{'body'}; } - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, @@ -200,19 +191,16 @@ sub new { - # path params + # path params if ( exists $args{'order_id'}) { my $_base_variable = "{" . "orderId" . "}"; - my $_base_value = WWW::SwaggerClient::APIClient::to_path_value($args{'order_id'}); + my $_base_value = $self->{api_client}->to_path_value($args{'order_id'}); $_resource_path =~ s/$_base_variable/$_base_value/g; } my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, @@ -261,19 +249,16 @@ sub new { - # path params + # path params if ( exists $args{'order_id'}) { my $_base_variable = "{" . "orderId" . "}"; - my $_base_value = WWW::SwaggerClient::APIClient::to_path_value($args{'order_id'}); + my $_base_value = $self->{api_client}->to_path_value($args{'order_id'}); $_resource_path =~ s/$_base_variable/$_base_value/g; } my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm index 2e5889ba39e..ece7f3e544b 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm @@ -28,9 +28,6 @@ use Carp qw( croak ); use Log::Any qw($log); -#use WWW::Swagger::Model::Category; -#use WWW::Swagger::Model::Pet; - use WWW::SwaggerClient::APIClient; @@ -98,14 +95,11 @@ sub new { my $_body_data; - # body params + # body params if ( exists $args{'body'}) { $_body_data = $args{'body'}; } - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, @@ -149,14 +143,11 @@ sub new { my $_body_data; - # body params + # body params if ( exists $args{'body'}) { $_body_data = $args{'body'}; } - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, @@ -200,14 +191,11 @@ sub new { my $_body_data; - # body params + # body params if ( exists $args{'body'}) { $_body_data = $args{'body'}; } - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, @@ -247,12 +235,12 @@ sub new { } $header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type(); - # query params + # query params if ( exists $args{'username'}) { - $query_params->{'username'} = WWW::::APIClient::to_query_value($args{'username'}); - } # query params + $query_params->{'username'} = $self->{api_client}->to_query_value($args{'username'}); + }# query params if ( exists $args{'password'}) { - $query_params->{'password'} = WWW::::APIClient::to_query_value($args{'password'}); + $query_params->{'password'} = $self->{api_client}->to_query_value($args{'password'}); } @@ -260,9 +248,6 @@ sub new { my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, @@ -310,9 +295,6 @@ sub new { my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, @@ -358,19 +340,16 @@ sub new { - # path params + # path params if ( exists $args{'username'}) { my $_base_variable = "{" . "username" . "}"; - my $_base_value = WWW::SwaggerClient::APIClient::to_path_value($args{'username'}); + my $_base_value = $self->{api_client}->to_path_value($args{'username'}); $_resource_path =~ s/$_base_variable/$_base_value/g; } my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, @@ -420,22 +399,19 @@ sub new { - # path params + # path params if ( exists $args{'username'}) { my $_base_variable = "{" . "username" . "}"; - my $_base_value = WWW::SwaggerClient::APIClient::to_path_value($args{'username'}); + my $_base_value = $self->{api_client}->to_path_value($args{'username'}); $_resource_path =~ s/$_base_variable/$_base_value/g; } my $_body_data; - # body params + # body params if ( exists $args{'body'}) { $_body_data = $args{'body'}; } - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, @@ -481,19 +457,16 @@ sub new { - # path params + # path params if ( exists $args{'username'}) { my $_base_variable = "{" . "username" . "}"; - my $_base_value = WWW::SwaggerClient::APIClient::to_path_value($args{'username'}); + my $_base_value = $self->{api_client}->to_path_value($args{'username'}); $_resource_path =~ s/$_base_variable/$_base_value/g; } my $_body_data; - # for HTTP post (form) - #$_body_data = $_body ? undef : $form_params; - # make the API Call $self->{api_client}->call_api($_resource_path, $_method, diff --git a/samples/client/petstore/perl/t/01_pet_api.t b/samples/client/petstore/perl/t/01_pet_api.t index 7855254e657..4a2ef58ee91 100644 --- a/samples/client/petstore/perl/t/01_pet_api.t +++ b/samples/client/petstore/perl/t/01_pet_api.t @@ -1,4 +1,4 @@ -use Test::More tests => 31; +use Test::More tests => 33; use Test::Exception; use lib 'lib'; @@ -10,8 +10,15 @@ use_ok('WWW::SwaggerClient::APIClient'); use_ok('WWW::SwaggerClient::Object::Pet'); use_ok('WWW::SwaggerClient::Object::Tag'); use_ok('WWW::SwaggerClient::Object::Category'); + +my $api_client = WWW::SwaggerClient::APIClient->new('base_url' => 'http://testing'); +my $pet_api = WWW::SwaggerClient::PetApi->new('api_client' => $api_client); +is $pet_api->{api_client}->{base_url}, 'http://testing', 'get the proper base URL from api client'; + my $api = WWW::SwaggerClient::PetApi->new(); +is $api->{api_client}->{base_url}, 'http://petstore.swagger.io/v2', 'get the default base URL from api client'; + # test select_header_content_type is $api->{api_client}->select_header_content_type('application/xml', 'Application/JSON'), 'application/json', 'get the proper content type application/json but not application/xml'; is $api->{api_client}->select_header_content_type('application/xml'), 'application/xml', 'get the proper content type application/json'; From 2c12312b9778643d0c94d9114b86e6d427a00aed Mon Sep 17 00:00:00 2001 From: wing328 Date: Wed, 27 May 2015 22:44:56 +0800 Subject: [PATCH 17/72] update user agent and add more test cases --- .../src/main/resources/perl/APIClient.mustache | 2 ++ .../src/main/resources/perl/Configuration.mustache | 8 +++++--- .../swagger-codegen/src/main/resources/perl/api.mustache | 7 +++---- .../petstore/perl/lib/WWW/SwaggerClient/APIClient.pm | 2 ++ .../petstore/perl/lib/WWW/SwaggerClient/Configuration.pm | 8 +++++--- .../client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm | 5 ++--- .../petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm | 5 ++--- .../client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm | 5 ++--- samples/client/petstore/perl/test.pl | 3 +++ 9 files changed, 26 insertions(+), 19 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache index 5d5dc0cdb96..79528dad23b 100644 --- a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache @@ -17,6 +17,8 @@ use Log::Any qw($log); use Carp; use Module::Runtime qw(use_module); +use WWW::{{invokerPackage}}::Configuration; + sub new { my $class = shift; diff --git a/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache b/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache index 0967dc136c3..07ff9b87785 100644 --- a/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache @@ -7,10 +7,12 @@ use utf8; use Log::Any qw($log); use Carp; +use WWW::{{invokerPackage}}::APIClient; + # class/static variables -my $api_client = WWW::SwaggerClient::APIClient->new; -my $http_timeout = 180; -my $http_user_agent = 'Perl-Swagger'; +our $api_client; +our $http_timeout = 180; +our $http_user_agent = 'Perl-Swagger'; 1; diff --git a/modules/swagger-codegen/src/main/resources/perl/api.mustache b/modules/swagger-codegen/src/main/resources/perl/api.mustache index 4996534c35e..54647ca4b8f 100644 --- a/modules/swagger-codegen/src/main/resources/perl/api.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/api.mustache @@ -27,11 +27,10 @@ use Exporter; use Carp qw( croak ); use Log::Any qw($log); +use WWW::{{invokerPackage}}::APIClient; +use WWW::{{invokerPackage}}::Configuration; {{#operations}} - -use WWW::{{invokerPackage}}::APIClient; - our @EXPORT_OK = qw( {{#operation}}{{{nickname}}} {{/operation}} @@ -39,7 +38,7 @@ our @EXPORT_OK = qw( sub new { my $class = shift; - my $default_api_client = WWW::{{invokerPackage}}::APIClient->new; + my $default_api_client = $WWW::{{invokerPackage}}::Configuration::api_client ? $WWW::{{invokerPackage}}::Configuration::api_client : WWW::{{invokerPackage}}::APIClient->new; my (%self) = ( 'api_client' => $default_api_client, @_ diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm index cf4ec0db4f3..3f6aaf9ff87 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm @@ -17,6 +17,8 @@ use Log::Any qw($log); use Carp; use Module::Runtime qw(use_module); +use WWW::SwaggerClient::Configuration; + sub new { my $class = shift; diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm index b8c57e66843..e3da7f3332d 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm @@ -7,10 +7,12 @@ use utf8; use Log::Any qw($log); use Carp; +use WWW::SwaggerClient::APIClient; + # class/static variables -my $api_client = WWW::SwaggerClient::APIClient->new; -my $http_timeout = 180; -my $http_user_agent = 'Perl-Swagger'; +our $api_client; +our $http_timeout = 180; +our $http_user_agent = 'Perl-Swagger'; 1; diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm index e796022bad1..077e7cbc45f 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm @@ -27,9 +27,8 @@ use Exporter; use Carp qw( croak ); use Log::Any qw($log); - - use WWW::SwaggerClient::APIClient; +use WWW::SwaggerClient::Configuration; our @EXPORT_OK = qw( update_pet @@ -45,7 +44,7 @@ our @EXPORT_OK = qw( sub new { my $class = shift; - my $default_api_client = WWW::SwaggerClient::APIClient->new; + my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::APIClient->new; my (%self) = ( 'api_client' => $default_api_client, @_ diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm index e457c99cac2..0c2d25d0236 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm @@ -27,9 +27,8 @@ use Exporter; use Carp qw( croak ); use Log::Any qw($log); - - use WWW::SwaggerClient::APIClient; +use WWW::SwaggerClient::Configuration; our @EXPORT_OK = qw( get_inventory @@ -41,7 +40,7 @@ our @EXPORT_OK = qw( sub new { my $class = shift; - my $default_api_client = WWW::SwaggerClient::APIClient->new; + my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::APIClient->new; my (%self) = ( 'api_client' => $default_api_client, @_ diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm index ece7f3e544b..ecdd8eab9c2 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm @@ -27,9 +27,8 @@ use Exporter; use Carp qw( croak ); use Log::Any qw($log); - - use WWW::SwaggerClient::APIClient; +use WWW::SwaggerClient::Configuration; our @EXPORT_OK = qw( create_user @@ -45,7 +44,7 @@ our @EXPORT_OK = qw( sub new { my $class = shift; - my $default_api_client = WWW::SwaggerClient::APIClient->new; + my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::APIClient->new; my (%self) = ( 'api_client' => $default_api_client, @_ diff --git a/samples/client/petstore/perl/test.pl b/samples/client/petstore/perl/test.pl index eb06f786f98..f1e819be5ce 100755 --- a/samples/client/petstore/perl/test.pl +++ b/samples/client/petstore/perl/test.pl @@ -6,6 +6,7 @@ use strict; use warnings; use WWW::SwaggerClient::PetApi; use WWW::SwaggerClient::APIClient; +use WWW::SwaggerClient::Configuration; use WWW::SwaggerClient::Object::Pet; use WWW::SwaggerClient::Object::Tag; use WWW::SwaggerClient::Object::Category; @@ -13,6 +14,8 @@ use JSON; use Data::Dumper; use DateTime; +$WWW::SwaggerClient::Configuration::http_user_agent = 'Perl-Swagger-Test'; + my $api = WWW::SwaggerClient::PetApi->new(); my $pet_id = 10008; From a9e767cbd8ed98c1b448bacabe84c533e0061c54 Mon Sep 17 00:00:00 2001 From: hrachya Date: Wed, 27 May 2015 17:19:34 -0700 Subject: [PATCH 18/72] Rolling back changes to deprecated class --- .../com/wordnik/swagger/codegen/Codegen.java | 36 +++---------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java index 76c95ae102f..c28031a9f27 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/Codegen.java @@ -47,33 +47,10 @@ public class Codegen extends DefaultGenerator { options.addOption("l", "lang", true, "client language to generate.\nAvailable languages include:\n\t[" + configString + "]"); options.addOption("o", "output", true, "where to write the generated files"); options.addOption("i", "input-spec", true, "location of the swagger spec, as URL or file"); + options.addOption("t", "template-dir", true, "folder containing the template files"); options.addOption("d", "debug-info", false, "prints additional info for debugging"); options.addOption("a", "auth", true, "adds authorization headers when fetching the swagger definitions remotely. Pass in a URL-encoded string of name:header with a comma separating multiple values"); - //adding additional options from language specific configs - Option existingOption; - for (Map.Entry configEntry : configs.entrySet()) { - for (CliOption langCliOption : configEntry.getValue().cliOptions()) { - //lang specific option - if (langCliOption.isLangSpecific()) { - //option exists, update description - if (options.hasOption(langCliOption.getOpt())) { - existingOption = options.getOption(langCliOption.getOpt()); - existingOption.setDescription(existingOption.getDescription() + "\n" + configEntry.getKey() + ": " + langCliOption.getDescription()); - } else { - //new option, prepend 'lang: ' to the description and add - langCliOption.setDescription(configEntry.getKey() + ": " + langCliOption.getDescription()); - options.addOption((Option) langCliOption); - } - } else { - //not lang specific, add if not already there - if (!options.hasOption(langCliOption.getOpt())) { - options.addOption((Option) langCliOption); - } - } - } - } - ClientOptInput clientOptInput = new ClientOptInput(); ClientOpts clientOpts = new ClientOpts(); Swagger swagger = null; @@ -113,13 +90,8 @@ public class Codegen extends DefaultGenerator { } if (cmd.hasOption("i")) swagger = new SwaggerParser().read(cmd.getOptionValue("i"), clientOptInput.getAuthorizationValues(), true); - - //add all passed cliOptions to clientOpts.properties - for (CliOption langCliOption : clientOptInput.getConfig().cliOptions()) { - if (cmd.hasOption(langCliOption.getOpt())) { - clientOpts.getProperties().put(langCliOption.getOpt(), String.valueOf(cmd.getOptionValue(langCliOption.getOpt()))); - } - } + if (cmd.hasOption("t")) + clientOpts.getProperties().put("templateDir", String.valueOf(cmd.getOptionValue("t"))); } catch (Exception e) { usage(options); @@ -168,4 +140,4 @@ public class Codegen extends DefaultGenerator { } } } -} +} \ No newline at end of file From 2cca1a8c2c8ec33f2b34a43bed172e55b0bc0c7b Mon Sep 17 00:00:00 2001 From: hrachya Date: Wed, 27 May 2015 17:22:44 -0700 Subject: [PATCH 19/72] Changing templateDir back to explicit option for cli --- .../main/java/com/wordnik/swagger/codegen/DefaultCodegen.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java index 6571990efc7..f7ec12b2c94 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java @@ -84,7 +84,7 @@ public class DefaultCodegen { } public void processOpts(){ - if(additionalProperties.containsKey("t")) { + if(additionalProperties.containsKey("templateDir")) { this.setTemplateDir((String)additionalProperties.get("t")); } @@ -303,7 +303,6 @@ public class DefaultCodegen { importMapping.put("LocalDate", "org.joda.time.*"); importMapping.put("LocalTime", "org.joda.time.*"); - cliOptions.add(new CliOption("t", "template-dir", true, "folder containing the template files")); cliOptions.add(new CliOption("modelPackage", "model-package", true, "Package for generated models")); cliOptions.add(new CliOption("apiPackage", "api-package", true, "Package for generated api classes")); } From c3055c7cc456b523e88dceb38bf2d639cfa4ae25 Mon Sep 17 00:00:00 2001 From: hrachya Date: Wed, 27 May 2015 17:30:42 -0700 Subject: [PATCH 20/72] Adding Config and ConfigParser classes --- .../src/main/java/config/Config.java | 38 +++++++++++++++ .../src/main/java/config/ConfigParser.java | 46 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 modules/swagger-codegen/src/main/java/config/Config.java create mode 100644 modules/swagger-codegen/src/main/java/config/ConfigParser.java diff --git a/modules/swagger-codegen/src/main/java/config/Config.java b/modules/swagger-codegen/src/main/java/config/Config.java new file mode 100644 index 00000000000..745824bd816 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/config/Config.java @@ -0,0 +1,38 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package config; + +import com.google.common.collect.ImmutableMap; +import java.util.HashMap; +import java.util.Map; + +public class Config { + private Map options; + + public Config() { + this.options = new HashMap(); + } + + public Config(Map properties) { + this.options = properties; + } + + public Map getOptions() { + return ImmutableMap.copyOf(options); + } + + public boolean hasOption(String opt){ + return options.containsKey(opt); + } + + public String getOption(String opt){ + return options.get(opt); + } + + public void setOption(String opt, String value){ + options.put(opt, value); + } +} diff --git a/modules/swagger-codegen/src/main/java/config/ConfigParser.java b/modules/swagger-codegen/src/main/java/config/ConfigParser.java new file mode 100644 index 00000000000..df2b37c2923 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/config/ConfigParser.java @@ -0,0 +1,46 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package config; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.util.Iterator; +import java.util.Map; + +public class ConfigParser { + + public static Config read(String location) { + + System.out.println("reading cofig from " + location); + + ObjectMapper mapper = new ObjectMapper(); + + Config config = new Config(); + + try { + JsonNode rootNode = mapper.readTree(new File(location)); + Iterator> optionNodes = rootNode.fields(); + + while (optionNodes.hasNext()) { + Map.Entry optionNode = (Map.Entry) optionNodes.next(); + + if(optionNode.getValue().isValueNode()){ + config.setOption(optionNode.getKey(), optionNode.getValue().asText()); + } + else{ + System.out.println("omitting non-value node " + optionNode.getKey()); + } + } + } + catch (Exception e) { + System.out.println(e.getMessage()); + return null; + } + + return config; + } +} From c9c58cbe4c6115af273dd290f13d867acc5ff30f Mon Sep 17 00:00:00 2001 From: hrachya Date: Wed, 27 May 2015 17:37:07 -0700 Subject: [PATCH 21/72] new -c/--config option for swagger-cli to specify json config file path setting options passed in config file if those were allowed by lang specific CodegenConfig --- .../wordnik/swagger/codegen/cmd/Generate.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/Generate.java b/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/Generate.java index 47449d84286..9bd2b5e0c24 100644 --- a/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/Generate.java +++ b/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/Generate.java @@ -1,10 +1,13 @@ package com.wordnik.swagger.codegen.cmd; +import com.wordnik.swagger.codegen.CliOption; import com.wordnik.swagger.codegen.ClientOptInput; import com.wordnik.swagger.codegen.ClientOpts; import com.wordnik.swagger.codegen.CodegenConfig; import com.wordnik.swagger.codegen.DefaultGenerator; import com.wordnik.swagger.models.Swagger; +import config.Config; +import config.ConfigParser; import io.airlift.airline.Command; import io.airlift.airline.Option; import io.swagger.parser.SwaggerParser; @@ -57,6 +60,9 @@ public class Generate implements Runnable { @Option( name= {"-D"}, title = "system properties", description = "sets specified system properties in " + "the format of name=value,name=value") private String systemProperties; + + @Option( name= {"-c", "--config"}, title = "configuration file", description = "path to json configuration file") + private String configFile; @Override public void run() { @@ -76,6 +82,17 @@ public class Generate implements Runnable { if (null != templateDir) { config.additionalProperties().put(TEMPLATE_DIR_PARAM, new File(templateDir).getAbsolutePath()); } + + if(null != configFile){ + Config genConfig = ConfigParser.read(configFile); + if (null != genConfig) { + for (CliOption langCliOption : config.cliOptions()) { + if (genConfig.hasOption(langCliOption.getOpt())) { + config.additionalProperties().put(langCliOption.getOpt(), genConfig.getOption(langCliOption.getOpt())); + } + } + } + } input.setConfig(config); From 1a868abdfa57dfccd4370d10187b72eaac580c08 Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 28 May 2015 10:51:36 +0800 Subject: [PATCH 22/72] rename APIClient to ApiClient --- .../wordnik/swagger/codegen/languages/PerlClientCodegen.java | 2 +- .../src/main/resources/perl/APIClient.mustache | 2 +- .../src/main/resources/perl/Configuration.mustache | 2 -- modules/swagger-codegen/src/main/resources/perl/api.mustache | 4 ++-- .../client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm | 2 +- .../petstore/perl/lib/WWW/SwaggerClient/Configuration.pm | 2 -- samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm | 4 ++-- .../client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm | 4 ++-- samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm | 4 ++-- samples/client/petstore/perl/t/01_pet_api.t | 4 ++-- samples/client/petstore/perl/test.pl | 2 +- 11 files changed, 14 insertions(+), 18 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java index 8f8ff21bc58..24a14135225 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java @@ -76,7 +76,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("array", "ARRAY"); typeMapping.put("map", "HASH"); - supportingFiles.add(new SupportingFile("APIClient.mustache", "lib/WWW/" + invokerPackage, "APIClient.pm")); + supportingFiles.add(new SupportingFile("ApiClient.mustache", "lib/WWW/" + invokerPackage, "ApiClient.pm")); supportingFiles.add(new SupportingFile("Configuration.mustache", "lib/WWW/" + invokerPackage, "Configuration.pm")); supportingFiles.add(new SupportingFile("BaseObject.mustache", "lib/WWW/" + invokerPackage, "Object/BaseObject.pm")); } diff --git a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache index 79528dad23b..d5fa48ac6d9 100644 --- a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache @@ -1,4 +1,4 @@ -package WWW::{{invokerPackage}}::APIClient; +package WWW::{{invokerPackage}}::ApiClient; use strict; use warnings; diff --git a/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache b/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache index 07ff9b87785..90ad999c8a9 100644 --- a/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache @@ -7,8 +7,6 @@ use utf8; use Log::Any qw($log); use Carp; -use WWW::{{invokerPackage}}::APIClient; - # class/static variables our $api_client; our $http_timeout = 180; diff --git a/modules/swagger-codegen/src/main/resources/perl/api.mustache b/modules/swagger-codegen/src/main/resources/perl/api.mustache index 54647ca4b8f..f1168d18ce7 100644 --- a/modules/swagger-codegen/src/main/resources/perl/api.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/api.mustache @@ -27,7 +27,7 @@ use Exporter; use Carp qw( croak ); use Log::Any qw($log); -use WWW::{{invokerPackage}}::APIClient; +use WWW::{{invokerPackage}}::ApiClient; use WWW::{{invokerPackage}}::Configuration; {{#operations}} @@ -38,7 +38,7 @@ our @EXPORT_OK = qw( sub new { my $class = shift; - my $default_api_client = $WWW::{{invokerPackage}}::Configuration::api_client ? $WWW::{{invokerPackage}}::Configuration::api_client : WWW::{{invokerPackage}}::APIClient->new; + my $default_api_client = $WWW::{{invokerPackage}}::Configuration::api_client ? $WWW::{{invokerPackage}}::Configuration::api_client : WWW::{{invokerPackage}}::ApiClient->new; my (%self) = ( 'api_client' => $default_api_client, @_ diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm index 3f6aaf9ff87..c80677ca518 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm @@ -1,4 +1,4 @@ -package WWW::SwaggerClient::APIClient; +package WWW::SwaggerClient::ApiClient; use strict; use warnings; diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm index e3da7f3332d..08982c445e1 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm @@ -7,8 +7,6 @@ use utf8; use Log::Any qw($log); use Carp; -use WWW::SwaggerClient::APIClient; - # class/static variables our $api_client; our $http_timeout = 180; diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm index 077e7cbc45f..92fdd50e5ef 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm @@ -27,7 +27,7 @@ use Exporter; use Carp qw( croak ); use Log::Any qw($log); -use WWW::SwaggerClient::APIClient; +use WWW::SwaggerClient::ApiClient; use WWW::SwaggerClient::Configuration; our @EXPORT_OK = qw( @@ -44,7 +44,7 @@ our @EXPORT_OK = qw( sub new { my $class = shift; - my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::APIClient->new; + my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::ApiClient->new; my (%self) = ( 'api_client' => $default_api_client, @_ diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm index 0c2d25d0236..b6d864a6be3 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm @@ -27,7 +27,7 @@ use Exporter; use Carp qw( croak ); use Log::Any qw($log); -use WWW::SwaggerClient::APIClient; +use WWW::SwaggerClient::ApiClient; use WWW::SwaggerClient::Configuration; our @EXPORT_OK = qw( @@ -40,7 +40,7 @@ our @EXPORT_OK = qw( sub new { my $class = shift; - my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::APIClient->new; + my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::ApiClient->new; my (%self) = ( 'api_client' => $default_api_client, @_ diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm index ecdd8eab9c2..fa0d9ed5c4f 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm @@ -27,7 +27,7 @@ use Exporter; use Carp qw( croak ); use Log::Any qw($log); -use WWW::SwaggerClient::APIClient; +use WWW::SwaggerClient::ApiClient; use WWW::SwaggerClient::Configuration; our @EXPORT_OK = qw( @@ -44,7 +44,7 @@ our @EXPORT_OK = qw( sub new { my $class = shift; - my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::APIClient->new; + my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::ApiClient->new; my (%self) = ( 'api_client' => $default_api_client, @_ diff --git a/samples/client/petstore/perl/t/01_pet_api.t b/samples/client/petstore/perl/t/01_pet_api.t index 4a2ef58ee91..6b731b846fe 100644 --- a/samples/client/petstore/perl/t/01_pet_api.t +++ b/samples/client/petstore/perl/t/01_pet_api.t @@ -6,12 +6,12 @@ use strict; use warnings; use_ok('WWW::SwaggerClient::PetApi'); -use_ok('WWW::SwaggerClient::APIClient'); +use_ok('WWW::SwaggerClient::ApiClient'); use_ok('WWW::SwaggerClient::Object::Pet'); use_ok('WWW::SwaggerClient::Object::Tag'); use_ok('WWW::SwaggerClient::Object::Category'); -my $api_client = WWW::SwaggerClient::APIClient->new('base_url' => 'http://testing'); +my $api_client = WWW::SwaggerClient::ApiClient->new('base_url' => 'http://testing'); my $pet_api = WWW::SwaggerClient::PetApi->new('api_client' => $api_client); is $pet_api->{api_client}->{base_url}, 'http://testing', 'get the proper base URL from api client'; diff --git a/samples/client/petstore/perl/test.pl b/samples/client/petstore/perl/test.pl index f1e819be5ce..3479f6bd3a9 100755 --- a/samples/client/petstore/perl/test.pl +++ b/samples/client/petstore/perl/test.pl @@ -5,7 +5,7 @@ use lib 'lib'; use strict; use warnings; use WWW::SwaggerClient::PetApi; -use WWW::SwaggerClient::APIClient; +use WWW::SwaggerClient::ApiClient; use WWW::SwaggerClient::Configuration; use WWW::SwaggerClient::Object::Pet; use WWW::SwaggerClient::Object::Tag; From 699f6fff4411672a6ce05bffe35d54293d8ba37f Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 28 May 2015 14:18:05 +0800 Subject: [PATCH 23/72] update file path --- .../swagger/codegen/languages/PerlClientCodegen.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java index 24a14135225..74670f27e09 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java @@ -27,7 +27,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig { public PerlClientCodegen() { super(); - modelPackage = "Object"; + modelPackage = "/Object"; outputFolder = "generated-code/perl"; modelTemplateFiles.put("object.mustache", ".pm"); apiTemplateFiles.put("api.mustache", ".pm"); @@ -76,9 +76,9 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("array", "ARRAY"); typeMapping.put("map", "HASH"); - supportingFiles.add(new SupportingFile("ApiClient.mustache", "lib/WWW/" + invokerPackage, "ApiClient.pm")); - supportingFiles.add(new SupportingFile("Configuration.mustache", "lib/WWW/" + invokerPackage, "Configuration.pm")); - supportingFiles.add(new SupportingFile("BaseObject.mustache", "lib/WWW/" + invokerPackage, "Object/BaseObject.pm")); + supportingFiles.add(new SupportingFile("ApiClient.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "ApiClient.pm")); + supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "Configuration.pm")); + supportingFiles.add(new SupportingFile("BaseObject.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "Object/BaseObject.pm")); } @Override @@ -88,11 +88,11 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String apiFileFolder() { - return outputFolder + "/lib/WWW/" + invokerPackage + apiPackage().replace('.', File.separatorChar); + return (outputFolder + "/lib/WWW/" + invokerPackage + apiPackage()).replace('/', File.separatorChar); } public String modelFileFolder() { - return outputFolder + "/lib/WWW/" + invokerPackage + "/" + modelPackage().replace('.', File.separatorChar); + return (outputFolder + "/lib/WWW/" + invokerPackage + modelPackage()).replace('/', File.separatorChar); } @Override From 61bc6522290c2f9eab73fdcfe6966e4a90d8ea16 Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 28 May 2015 14:34:39 +0800 Subject: [PATCH 24/72] use file separator --- .../swagger/codegen/languages/CSharpClientCodegen.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java index a2463c8a10b..afba07c9566 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java @@ -97,11 +97,11 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig @Override public String apiFileFolder() { - return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar); + return (outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', '/')).replace('.', File.separatorChar); } public String modelFileFolder() { - return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); + return (outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', '/')).replace('.', File.separatorChar); } @Override From e993d0856359b3a6b2ef9bc7d98b60cd4ccd08c3 Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 28 May 2015 15:06:31 +0800 Subject: [PATCH 25/72] rename APIClient to ApiClient, APIClientException to APIException --- .../codegen/languages/PhpClientCodegen.java | 4 +- .../src/main/resources/php/APIClient.mustache | 12 ++--- ...ception.mustache => ApiException.mustache} | 2 +- .../src/main/resources/php/api.mustache | 4 +- .../main/resources/php/configuration.mustache | 6 +-- .../php/SwaggerClient-php/lib/APIClient.php | 12 ++--- ...PIClientException.php => ApiException.php} | 2 +- .../SwaggerClient-php/lib/Configuration.php | 6 +-- .../php/SwaggerClient-php/lib/PetApi.php | 4 +- .../php/SwaggerClient-php/lib/StoreApi.php | 4 +- .../php/SwaggerClient-php/lib/UserApi.php | 4 +- .../SwaggerClient-php/tests/PetApiTest.php | 44 +++++++++---------- samples/client/petstore/php/test.php | 2 +- 13 files changed, 53 insertions(+), 53 deletions(-) rename modules/swagger-codegen/src/main/resources/php/{APIClientException.mustache => ApiException.mustache} (95%) rename samples/client/petstore/php/SwaggerClient-php/lib/{APIClientException.php => ApiException.php} (95%) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java index 55d358154f8..dd50d623e5f 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java @@ -85,8 +85,8 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { supportingFiles.add(new SupportingFile("composer.mustache", packagePath, "composer.json")); supportingFiles.add(new SupportingFile("configuration.mustache", packagePath + "/lib", "Configuration.php")); - supportingFiles.add(new SupportingFile("APIClient.mustache", packagePath + "/lib", "APIClient.php")); - supportingFiles.add(new SupportingFile("APIClientException.mustache", packagePath + "/lib", "APIClientException.php")); + supportingFiles.add(new SupportingFile("ApiClient.mustache", packagePath + "/lib", "ApiClient.php")); + supportingFiles.add(new SupportingFile("ApiException.mustache", packagePath + "/lib", "ApiException.php")); supportingFiles.add(new SupportingFile("require.mustache", packagePath, invokerPackage + ".php")); } diff --git a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache index 88954ffad3b..cadce36f64d 100644 --- a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache @@ -17,7 +17,7 @@ namespace {{invokerPackage}}; -class APIClient { +class ApiClient { public static $PATCH = "PATCH"; public static $POST = "POST"; @@ -173,7 +173,7 @@ class APIClient { * @param array $headerParams parameters to be place in request header * @return mixed */ - public function callAPI($resourcePath, $method, $queryParams, $postData, + public function callApi($resourcePath, $method, $queryParams, $postData, $headerParams, $authSettings) { $headers = array(); @@ -228,7 +228,7 @@ class APIClient { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); } else if ($method != self::$GET) { - throw new APIClientException('Method ' . $method . ' is not recognized.'); + throw new ApiException('Method ' . $method . ' is not recognized.'); } curl_setopt($curl, CURLOPT_URL, $url); @@ -256,7 +256,7 @@ class APIClient { // Handle the response if ($response_info['http_code'] == 0) { - throw new APIClientException("TIMEOUT: api call to " . $url . + throw new ApiException("TIMEOUT: api call to " . $url . " took more than 5s to return", 0, $response_info, $response); } else if ($response_info['http_code'] >= 200 && $response_info['http_code'] <= 299 ) { $data = json_decode($response); @@ -264,12 +264,12 @@ class APIClient { $data = $response; } } else if ($response_info['http_code'] == 401) { - throw new APIClientException("Unauthorized API request to " . $url . + throw new ApiException("Unauthorized API request to " . $url . ": " . serialize($response), 0, $response_info, $response); } else if ($response_info['http_code'] == 404) { $data = null; } else { - throw new APIClientException("Can't connect to the api: " . $url . + throw new ApiException("Can't connect to the api: " . $url . " response code: " . $response_info['http_code'], 0, $response_info, $response); } diff --git a/modules/swagger-codegen/src/main/resources/php/APIClientException.mustache b/modules/swagger-codegen/src/main/resources/php/ApiException.mustache similarity index 95% rename from modules/swagger-codegen/src/main/resources/php/APIClientException.mustache rename to modules/swagger-codegen/src/main/resources/php/ApiException.mustache index 3cf74d69288..58a75eabeb1 100644 --- a/modules/swagger-codegen/src/main/resources/php/APIClientException.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiException.mustache @@ -19,7 +19,7 @@ namespace {{invokerPackage}}; use \Exception; -class APIClientException extends Exception { +class ApiException extends Exception { protected $response, $response_info; public function __construct($message="", $code=0, $response_info=null, $response=null) { diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 1c32eeb01c5..6b4e6e3db16 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -28,7 +28,7 @@ class {{classname}} { function __construct($apiClient = null) { if (null === $apiClient) { if (Configuration::$apiClient === null) { - Configuration::$apiClient = new APIClient(); // create a new API client if not present + Configuration::$apiClient = new ApiClient(); // create a new API client if not present $this->apiClient = Configuration::$apiClient; } else @@ -38,7 +38,7 @@ class {{classname}} { } } - private $apiClient; // instance of the APIClient + private $apiClient; // instance of the ApiClient /** * get the API client diff --git a/modules/swagger-codegen/src/main/resources/php/configuration.mustache b/modules/swagger-codegen/src/main/resources/php/configuration.mustache index 5528e8076f3..ea5f813b5e0 100644 --- a/modules/swagger-codegen/src/main/resources/php/configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/php/configuration.mustache @@ -31,7 +31,7 @@ class Configuration { public static $username = ''; public static $password = ''; - // an instance of APIClient + // an instance of ApiClient public static $apiClient; // debugging @@ -39,11 +39,11 @@ class Configuration { public static $debug_file = 'php://output'; //output debug log to STDOUT by default /* - * manually initalize API client + * manually initalize Api client */ public static function init() { if (self::$apiClient === null) - self::$apiClient = new APIClient(); + self::$apiClient = new ApiClient(); } } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php index 3e9119003d7..5b3289b5a29 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php @@ -17,7 +17,7 @@ namespace SwaggerClient; -class APIClient { +class ApiClient { public static $PATCH = "PATCH"; public static $POST = "POST"; @@ -178,7 +178,7 @@ class APIClient { * @param array $headerParams parameters to be place in request header * @return mixed */ - public function callAPI($resourcePath, $method, $queryParams, $postData, + public function callApi($resourcePath, $method, $queryParams, $postData, $headerParams, $authSettings) { $headers = array(); @@ -233,7 +233,7 @@ class APIClient { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); } else if ($method != self::$GET) { - throw new APIClientException('Method ' . $method . ' is not recognized.'); + throw new ApiException('Method ' . $method . ' is not recognized.'); } curl_setopt($curl, CURLOPT_URL, $url); @@ -261,7 +261,7 @@ class APIClient { // Handle the response if ($response_info['http_code'] == 0) { - throw new APIClientException("TIMEOUT: api call to " . $url . + throw new ApiException("TIMEOUT: api call to " . $url . " took more than 5s to return", 0, $response_info, $response); } else if ($response_info['http_code'] >= 200 && $response_info['http_code'] <= 299 ) { $data = json_decode($response); @@ -269,12 +269,12 @@ class APIClient { $data = $response; } } else if ($response_info['http_code'] == 401) { - throw new APIClientException("Unauthorized API request to " . $url . + throw new ApiException("Unauthorized API request to " . $url . ": " . serialize($response), 0, $response_info, $response); } else if ($response_info['http_code'] == 404) { $data = null; } else { - throw new APIClientException("Can't connect to the api: " . $url . + throw new ApiException("Can't connect to the api: " . $url . " response code: " . $response_info['http_code'], 0, $response_info, $response); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/APIClientException.php b/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php similarity index 95% rename from samples/client/petstore/php/SwaggerClient-php/lib/APIClientException.php rename to samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php index 8d83da0186e..8b8244718ee 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/APIClientException.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php @@ -19,7 +19,7 @@ namespace SwaggerClient; use \Exception; -class APIClientException extends Exception { +class ApiException extends Exception { protected $response, $response_info; public function __construct($message="", $code=0, $response_info=null, $response=null) { diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php index fe4cbc59998..a3412c93eb6 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php @@ -31,7 +31,7 @@ class Configuration { public static $username = ''; public static $password = ''; - // an instance of APIClient + // an instance of ApiClient public static $apiClient; // debugging @@ -39,11 +39,11 @@ class Configuration { public static $debug_file = 'php://output'; //output debug log to STDOUT by default /* - * manually initalize API client + * manually initalize Api client */ public static function init() { if (self::$apiClient === null) - self::$apiClient = new APIClient(); + self::$apiClient = new ApiClient(); } } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/PetApi.php b/samples/client/petstore/php/SwaggerClient-php/lib/PetApi.php index 9456f42bc15..338646bfefe 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/PetApi.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/PetApi.php @@ -27,7 +27,7 @@ class PetApi { function __construct($apiClient = null) { if (null === $apiClient) { if (Configuration::$apiClient === null) { - Configuration::$apiClient = new APIClient(); // create a new API client if not present + Configuration::$apiClient = new ApiClient(); // create a new API client if not present $this->apiClient = Configuration::$apiClient; } else @@ -37,7 +37,7 @@ class PetApi { } } - private $apiClient; // instance of the APIClient + private $apiClient; // instance of the ApiClient /** * get the API client diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/StoreApi.php b/samples/client/petstore/php/SwaggerClient-php/lib/StoreApi.php index 629201965dc..73a060f421d 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/StoreApi.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/StoreApi.php @@ -27,7 +27,7 @@ class StoreApi { function __construct($apiClient = null) { if (null === $apiClient) { if (Configuration::$apiClient === null) { - Configuration::$apiClient = new APIClient(); // create a new API client if not present + Configuration::$apiClient = new ApiClient(); // create a new API client if not present $this->apiClient = Configuration::$apiClient; } else @@ -37,7 +37,7 @@ class StoreApi { } } - private $apiClient; // instance of the APIClient + private $apiClient; // instance of the ApiClient /** * get the API client diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/UserApi.php b/samples/client/petstore/php/SwaggerClient-php/lib/UserApi.php index 0f4a1bf2dac..1e4f7dbc293 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/UserApi.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/UserApi.php @@ -27,7 +27,7 @@ class UserApi { function __construct($apiClient = null) { if (null === $apiClient) { if (Configuration::$apiClient === null) { - Configuration::$apiClient = new APIClient(); // create a new API client if not present + Configuration::$apiClient = new ApiClient(); // create a new API client if not present $this->apiClient = Configuration::$apiClient; } else @@ -37,7 +37,7 @@ class UserApi { } } - private $apiClient; // instance of the APIClient + private $apiClient; // instance of the ApiClient /** * get the API client diff --git a/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php b/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php index 85f0c900a6c..d02b8e74558 100644 --- a/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php +++ b/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php @@ -11,7 +11,7 @@ class PetApiTest extends \PHPUnit_Framework_TestCase //SwaggerClient\Configuration::$debug = true; // skip initializing the API client as it should be automatic - //$api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); + //$api_client = new SwaggerClient\ApiClient('http://petstore.swagger.io/v2'); // new pet $new_pet_id = 10005; $new_pet = new SwaggerClient\models\Pet; @@ -34,36 +34,36 @@ class PetApiTest extends \PHPUnit_Framework_TestCase $add_response = $pet_api->addPet($new_pet); } - // test static functions defined in APIClient - public function testAPIClient() + // test static functions defined in ApiClient + public function testApiClient() { // test selectHeaderAccept - $this->assertSame('application/json', SwaggerClient\APIClient::selectHeaderAccept(array('application/xml','application/json'))); - $this->assertSame(NULL, SwaggerClient\APIClient::selectHeaderAccept(array())); - $this->assertSame('application/yaml,application/xml', SwaggerClient\APIClient::selectHeaderAccept(array('application/yaml','application/xml'))); + $this->assertSame('application/json', SwaggerClient\ApiClient::selectHeaderAccept(array('application/xml','application/json'))); + $this->assertSame(NULL, SwaggerClient\ApiClient::selectHeaderAccept(array())); + $this->assertSame('application/yaml,application/xml', SwaggerClient\ApiClient::selectHeaderAccept(array('application/yaml','application/xml'))); // test selectHeaderContentType - $this->assertSame('application/json', SwaggerClient\APIClient::selectHeaderContentType(array('application/xml','application/json'))); - $this->assertSame('application/json', SwaggerClient\APIClient::selectHeaderContentType(array())); - $this->assertSame('application/yaml,application/xml', SwaggerClient\APIClient::selectHeaderContentType(array('application/yaml','application/xml'))); + $this->assertSame('application/json', SwaggerClient\ApiClient::selectHeaderContentType(array('application/xml','application/json'))); + $this->assertSame('application/json', SwaggerClient\ApiClient::selectHeaderContentType(array())); + $this->assertSame('application/yaml,application/xml', SwaggerClient\ApiClient::selectHeaderContentType(array('application/yaml','application/xml'))); // test addDefaultHeader and getDefaultHeader - SwaggerClient\APIClient::addDefaultHeader('test1', 'value1'); - SwaggerClient\APIClient::addDefaultHeader('test2', 200); - $defaultHeader = SwaggerClient\APIClient::getDefaultHeader(); + SwaggerClient\ApiClient::addDefaultHeader('test1', 'value1'); + SwaggerClient\ApiClient::addDefaultHeader('test2', 200); + $defaultHeader = SwaggerClient\ApiClient::getDefaultHeader(); $this->assertSame('value1', $defaultHeader['test1']); $this->assertSame(200, $defaultHeader['test2']); // test deleteDefaultHeader - SwaggerClient\APIClient::deleteDefaultHeader('test2'); - $defaultHeader = SwaggerClient\APIClient::getDefaultHeader(); + SwaggerClient\ApiClient::deleteDefaultHeader('test2'); + $defaultHeader = SwaggerClient\ApiClient::getDefaultHeader(); $this->assertFalse(isset($defaultHeader['test2'])); $pet_api = new SwaggerClient\PetAPI(); $pet_api2 = new SwaggerClient\PetAPI(); - $apiClient3 = new SwaggerClient\APIClient(); + $apiClient3 = new SwaggerClient\ApiClient(); $apiClient3->setUserAgent = 'api client 3'; - $apiClient4 = new SwaggerClient\APIClient(); + $apiClient4 = new SwaggerClient\ApiClient(); $apiClient4->setUserAgent = 'api client 4'; $pet_api3 = new SwaggerClient\PetAPI($apiClient3); @@ -88,7 +88,7 @@ class PetApiTest extends \PHPUnit_Framework_TestCase public function testGetPetById() { // initialize the API client without host - $api_client = new SwaggerClient\APIClient(); + $api_client = new SwaggerClient\ApiClient(); SwaggerClient\Configuration::$apiKey['api_key'] = '111222333444555'; $pet_id = 10005; // ID of pet that needs to be fetched $pet_api = new SwaggerClient\PetAPI($api_client); @@ -106,7 +106,7 @@ class PetApiTest extends \PHPUnit_Framework_TestCase public function testFindPetByStatus() { // initialize the API client - $api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); + $api_client = new SwaggerClient\ApiClient('http://petstore.swagger.io/v2'); $pet_api = new SwaggerClient\PetAPI($api_client); // return Pet (model) $response = $pet_api->findPetsByStatus("available"); @@ -125,7 +125,7 @@ class PetApiTest extends \PHPUnit_Framework_TestCase public function testUpdatePet() { // initialize the API client - $api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); + $api_client = new SwaggerClient\ApiClient('http://petstore.swagger.io/v2'); $pet_id = 10001; // ID of pet that needs to be fetched $pet_api = new SwaggerClient\PetAPI($api_client); // create updated pet object @@ -148,7 +148,7 @@ class PetApiTest extends \PHPUnit_Framework_TestCase public function testUpdatePetWithForm() { // initialize the API client - $api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); + $api_client = new SwaggerClient\ApiClient('http://petstore.swagger.io/v2'); $pet_id = 10001; // ID of pet that needs to be fetched $pet_api = new SwaggerClient\PetAPI($api_client); // update Pet (form) @@ -165,7 +165,7 @@ class PetApiTest extends \PHPUnit_Framework_TestCase public function testAddPet() { // initialize the API client - $api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); + $api_client = new SwaggerClient\ApiClient('http://petstore.swagger.io/v2'); $new_pet_id = 10001; $new_pet = new SwaggerClient\models\Pet; $new_pet->id = $new_pet_id; @@ -185,7 +185,7 @@ class PetApiTest extends \PHPUnit_Framework_TestCase public function testUploadFile() { // initialize the API client - $api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); + $api_client = new SwaggerClient\ApiClient('http://petstore.swagger.io/v2'); $pet_api = new SwaggerClient\PetAPI($api_client); // upload file $pet_id = 10001; diff --git a/samples/client/petstore/php/test.php b/samples/client/petstore/php/test.php index 4b63c75f472..0721d7614f2 100644 --- a/samples/client/petstore/php/test.php +++ b/samples/client/petstore/php/test.php @@ -3,7 +3,7 @@ require_once('SwaggerClient-php/SwaggerClient.php'); // initialize the API client -//$api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); +//$api_client = new SwaggerClient\ApiClient('http://petstore.swagger.io/v2'); //$api_client->addDefaultHeader("test1", "value1"); // to enable logging From 412fcf11f9312eb77d65d6a4d8593e584e9bb036 Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 28 May 2015 15:19:05 +0800 Subject: [PATCH 26/72] update file separator --- .../codegen/languages/PhpClientCodegen.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java index dd50d623e5f..6fb7a7d70c1 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java @@ -83,11 +83,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("array", "array"); typeMapping.put("list", "array"); - supportingFiles.add(new SupportingFile("composer.mustache", packagePath, "composer.json")); - supportingFiles.add(new SupportingFile("configuration.mustache", packagePath + "/lib", "Configuration.php")); - supportingFiles.add(new SupportingFile("ApiClient.mustache", packagePath + "/lib", "ApiClient.php")); - supportingFiles.add(new SupportingFile("ApiException.mustache", packagePath + "/lib", "ApiException.php")); - supportingFiles.add(new SupportingFile("require.mustache", packagePath, invokerPackage + ".php")); + supportingFiles.add(new SupportingFile("composer.mustache", packagePath.replace('/', File.separatorChar), "composer.json")); + supportingFiles.add(new SupportingFile("configuration.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "Configuration.php")); + supportingFiles.add(new SupportingFile("ApiClient.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "ApiClient.php")); + supportingFiles.add(new SupportingFile("ApiException.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "ApiException.php")); + supportingFiles.add(new SupportingFile("require.mustache", packagePath.replace('/', File.separatorChar), invokerPackage + ".php")); } @Override @@ -97,11 +97,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String apiFileFolder() { - return outputFolder + "/" + apiPackage().replace('.', File.separatorChar); + return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar); } public String modelFileFolder() { - return outputFolder + "/" + modelPackage().replace('.', File.separatorChar); + return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar); } @Override From 165efdbdbbe8b79c78f80a88d8270cbacc49aee7 Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 28 May 2015 18:24:03 +0800 Subject: [PATCH 27/72] rename apiinvoker to apiclient, add configuration, make apiclient an instance --- .../languages/CSharpClientCodegen.java | 8 ++-- ...apiInvoker.mustache => ApiClient.mustache} | 12 +++--- .../resources/csharp/Configuration.mustache | 14 +++++++ .../src/main/resources/csharp/api.mustache | 20 +++++++-- .../src/main/csharp/io/swagger/Api/PetApi.cs | 41 +++++++++++-------- .../main/csharp/io/swagger/Api/StoreApi.cs | 29 ++++++++----- .../src/main/csharp/io/swagger/Api/UserApi.cs | 41 +++++++++++-------- .../client/{ApiInvoker.cs => ApiClient.cs} | 12 +++--- .../csharp/io/swagger/client/Configuration.cs | 14 +++++++ 9 files changed, 128 insertions(+), 63 deletions(-) rename modules/swagger-codegen/src/main/resources/csharp/{apiInvoker.mustache => ApiClient.mustache} (92%) create mode 100644 modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache rename samples/client/petstore/csharp/src/main/csharp/io/swagger/client/{ApiInvoker.cs => ApiClient.cs} (92%) create mode 100644 samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java index 9de427058a1..ceb4849bd2a 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/CSharpClientCodegen.java @@ -41,9 +41,11 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig additionalProperties.put("invokerPackage", invokerPackage); - supportingFiles.add(new SupportingFile("apiInvoker.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.cs")); - supportingFiles.add(new SupportingFile("apiException.mustache", + supportingFiles.add(new SupportingFile("Configuration.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "Configuration.cs")); + supportingFiles.add(new SupportingFile("ApiClient.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiClient.cs")); + supportingFiles.add(new SupportingFile("ApiException.mustache", (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.cs")); supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll")); supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat")); diff --git a/modules/swagger-codegen/src/main/resources/csharp/apiInvoker.mustache b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache similarity index 92% rename from modules/swagger-codegen/src/main/resources/csharp/apiInvoker.mustache rename to modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache index 01406a8add0..469d5e94c37 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/apiInvoker.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache @@ -8,13 +8,15 @@ using Newtonsoft.Json; using RestSharp; namespace {{invokerPackage}} { - public class ApiInvoker { - public ApiInvoker() { + public class ApiClient { + public ApiClient() { this.basePath = "{{basePath}}"; + this.restClient = new RestClient(this.basePath); } - public ApiInvoker(String basePath) { + public ApiClient(String basePath) { this.basePath = basePath; + this.restClient = new RestClient(this.basePath); } public string basePath { get; set; } @@ -43,10 +45,10 @@ namespace {{invokerPackage}} { request.AddParameter(param.Key, param.Value); // add file parameter, if any - foreach(KeyValuePair param in FormParams) + foreach(KeyValuePair param in FileParams) request.AddFile(param.Key, param.Value); - if (PostBody == null) { + if (PostBody != null) { request.AddParameter("application/json", PostBody, ParameterType.RequestBody); // http body (model) parameter } diff --git a/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache b/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache new file mode 100644 index 00000000000..41c371be487 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using {{invokerPackage}}; + +namespace {{invokerPackage}} { + public class Configuration{ + public static ApiClient apiClient = new ApiClient(); + + } +} diff --git a/modules/swagger-codegen/src/main/resources/csharp/api.mustache b/modules/swagger-codegen/src/main/resources/csharp/api.mustache index ee3f326c746..c78b7461c7e 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/api.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/api.mustache @@ -10,12 +10,25 @@ namespace {{package}} { {{#operations}} public class {{classname}} { string basePath; - public ApiInvoker apiClient {get; set;} + public ApiClient apiClient {get; set;} public {{classname}}(String basePath = "{{basePath}}") { this.basePath = basePath; - this.apiClient = new ApiInvoker(basePath); + this.apiClient = new ApiClient(basePath); + } + + /// + /// Create a new object + /// + /// an instance of ApiClient + /// + public {{classname}}(ApiClient apiClient = null) { + if (apiClient == null) { // use the default one in Configuration + this.apiClient = Configuration.apiClient; + } else { + this.apiClient = apiClient; + } } /// @@ -36,7 +49,6 @@ namespace {{package}} { } {{#operation}} - /// /// {{summary}} {{notes}} /// @@ -71,7 +83,7 @@ namespace {{package}} { {{/bodyParam}} // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("{{path}}", Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content); diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs index 054cb1bc204..4c7cd680bed 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs @@ -8,12 +8,25 @@ namespace IO.Swagger.Api { public class PetApi { string basePath; - public ApiInvoker apiClient {get; set;} + public ApiClient apiClient {get; set;} public PetApi(String basePath = "http://petstore.swagger.io/v2") { this.basePath = basePath; - this.apiClient = new ApiInvoker(basePath); + this.apiClient = new ApiClient(basePath); + } + + /// + /// Create a new object + /// + /// an instance of ApiClient + /// + public PetApi(ApiClient apiClient = null) { + if (apiClient == null) { // use the default one in Configuration + this.apiClient = Configuration.apiClient; + } else { + this.apiClient = apiClient; + } } /// @@ -34,7 +47,6 @@ namespace IO.Swagger.Api { } - /// /// Update an existing pet /// @@ -61,7 +73,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/pet", Method.PUT, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.PUT, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UpdatePet: " + response.Content); @@ -70,7 +82,6 @@ namespace IO.Swagger.Api { return; } - /// /// Add a new pet to the store /// @@ -97,7 +108,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/pet", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling AddPet: " + response.Content); @@ -106,7 +117,6 @@ namespace IO.Swagger.Api { return; } - /// /// Finds Pets by status Multiple status values can be provided with comma seperated strings /// @@ -133,7 +143,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/findByStatus", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling FindPetsByStatus: " + response.Content); @@ -141,7 +151,6 @@ namespace IO.Swagger.Api { return (List) apiClient.Deserialize(response.Content, typeof(List)); } - /// /// Finds Pets by tags Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing. /// @@ -168,7 +177,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/findByTags", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling FindPetsByTags: " + response.Content); @@ -176,7 +185,6 @@ namespace IO.Swagger.Api { return (List) apiClient.Deserialize(response.Content, typeof(List)); } - /// /// Find pet by ID Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions /// @@ -206,7 +214,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/{petId}", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetPetById: " + response.Content); @@ -214,7 +222,6 @@ namespace IO.Swagger.Api { return (Pet) apiClient.Deserialize(response.Content, typeof(Pet)); } - /// /// Updates a pet in the store with form data /// @@ -248,7 +255,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/{petId}", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UpdatePetWithForm: " + response.Content); @@ -257,7 +264,6 @@ namespace IO.Swagger.Api { return; } - /// /// Deletes a pet /// @@ -289,7 +295,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/{petId}", Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling DeletePet: " + response.Content); @@ -298,7 +304,6 @@ namespace IO.Swagger.Api { return; } - /// /// uploads an image /// @@ -332,7 +337,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/pet/{petId}/uploadImage", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UploadFile: " + response.Content); diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs index 9d10a095c44..9fa4a528a07 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs @@ -8,12 +8,25 @@ namespace IO.Swagger.Api { public class StoreApi { string basePath; - public ApiInvoker apiClient {get; set;} + public ApiClient apiClient {get; set;} public StoreApi(String basePath = "http://petstore.swagger.io/v2") { this.basePath = basePath; - this.apiClient = new ApiInvoker(basePath); + this.apiClient = new ApiClient(basePath); + } + + /// + /// Create a new object + /// + /// an instance of ApiClient + /// + public StoreApi(ApiClient apiClient = null) { + if (apiClient == null) { // use the default one in Configuration + this.apiClient = Configuration.apiClient; + } else { + this.apiClient = apiClient; + } } /// @@ -34,7 +47,6 @@ namespace IO.Swagger.Api { } - /// /// Returns pet inventories by status Returns a map of status codes to quantities /// @@ -59,7 +71,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/store/inventory", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetInventory: " + response.Content); @@ -67,7 +79,6 @@ namespace IO.Swagger.Api { return (Dictionary) apiClient.Deserialize(response.Content, typeof(Dictionary)); } - /// /// Place an order for a pet /// @@ -94,7 +105,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/store/order", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling PlaceOrder: " + response.Content); @@ -102,7 +113,6 @@ namespace IO.Swagger.Api { return (Order) apiClient.Deserialize(response.Content, typeof(Order)); } - /// /// Find purchase order by ID For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions /// @@ -132,7 +142,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/store/order/{orderId}", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetOrderById: " + response.Content); @@ -140,7 +150,6 @@ namespace IO.Swagger.Api { return (Order) apiClient.Deserialize(response.Content, typeof(Order)); } - /// /// Delete purchase order by ID For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors /// @@ -170,7 +179,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/store/order/{orderId}", Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling DeleteOrder: " + response.Content); diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs index c225f45496d..0d6707d88cf 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs @@ -8,12 +8,25 @@ namespace IO.Swagger.Api { public class UserApi { string basePath; - public ApiInvoker apiClient {get; set;} + public ApiClient apiClient {get; set;} public UserApi(String basePath = "http://petstore.swagger.io/v2") { this.basePath = basePath; - this.apiClient = new ApiInvoker(basePath); + this.apiClient = new ApiClient(basePath); + } + + /// + /// Create a new object + /// + /// an instance of ApiClient + /// + public UserApi(ApiClient apiClient = null) { + if (apiClient == null) { // use the default one in Configuration + this.apiClient = Configuration.apiClient; + } else { + this.apiClient = apiClient; + } } /// @@ -34,7 +47,6 @@ namespace IO.Swagger.Api { } - /// /// Create user This can only be done by the logged in user. /// @@ -61,7 +73,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/user", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling CreateUser: " + response.Content); @@ -70,7 +82,6 @@ namespace IO.Swagger.Api { return; } - /// /// Creates list of users with given input array /// @@ -97,7 +108,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/user/createWithArray", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling CreateUsersWithArrayInput: " + response.Content); @@ -106,7 +117,6 @@ namespace IO.Swagger.Api { return; } - /// /// Creates list of users with given input array /// @@ -133,7 +143,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/user/createWithList", Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling CreateUsersWithListInput: " + response.Content); @@ -142,7 +152,6 @@ namespace IO.Swagger.Api { return; } - /// /// Logs user into the system /// @@ -171,7 +180,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/user/login", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling LoginUser: " + response.Content); @@ -179,7 +188,6 @@ namespace IO.Swagger.Api { return (string) apiClient.Deserialize(response.Content, typeof(string)); } - /// /// Logs out current logged in user session /// @@ -204,7 +212,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/user/logout", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling LogoutUser: " + response.Content); @@ -213,7 +221,6 @@ namespace IO.Swagger.Api { return; } - /// /// Get user by user name /// @@ -243,7 +250,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/user/{username}", Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetUserByName: " + response.Content); @@ -251,7 +258,6 @@ namespace IO.Swagger.Api { return (User) apiClient.Deserialize(response.Content, typeof(User)); } - /// /// Updated user This can only be done by the logged in user. /// @@ -283,7 +289,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/user/{username}", Method.PUT, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.PUT, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UpdateUser: " + response.Content); @@ -292,7 +298,6 @@ namespace IO.Swagger.Api { return; } - /// /// Delete user This can only be done by the logged in user. /// @@ -322,7 +327,7 @@ namespace IO.Swagger.Api { // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi("/user/{username}", Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling DeleteUser: " + response.Content); diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiInvoker.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs similarity index 92% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiInvoker.cs rename to samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs index ce5cf0263eb..2a48e4b3075 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiInvoker.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs @@ -8,13 +8,15 @@ using Newtonsoft.Json; using RestSharp; namespace IO.Swagger.Client { - public class ApiInvoker { - public ApiInvoker() { + public class ApiClient { + public ApiClient() { this.basePath = "http://petstore.swagger.io/v2"; + this.restClient = new RestClient(this.basePath); } - public ApiInvoker(String basePath) { + public ApiClient(String basePath) { this.basePath = basePath; + this.restClient = new RestClient(this.basePath); } public string basePath { get; set; } @@ -43,10 +45,10 @@ namespace IO.Swagger.Client { request.AddParameter(param.Key, param.Value); // add file parameter, if any - foreach(KeyValuePair param in FormParams) + foreach(KeyValuePair param in FileParams) request.AddFile(param.Key, param.Value); - if (PostBody == null) { + if (PostBody != null) { request.AddParameter("application/json", PostBody, ParameterType.RequestBody); // http body (model) parameter } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs new file mode 100644 index 00000000000..815bb027c8f --- /dev/null +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using IO.Swagger.Client; + +namespace IO.Swagger.Client { + public class Configuration{ + public static ApiClient apiClient = new ApiClient(); + + } +} From 2edcd820942a960341864878b737c8416b6d50e9 Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 28 May 2015 19:16:26 +0800 Subject: [PATCH 28/72] minor fix to output path --- .../wordnik/swagger/codegen/languages/ObjcClientCodegen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java index d1e227ce744..957c784fd6a 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java @@ -26,7 +26,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { public ObjcClientCodegen() { super(); - outputFolder = "generated-code/objc"; + outputFolder = "generated-code" + File.separator + "objc"; modelTemplateFiles.put("model-header.mustache", ".h"); modelTemplateFiles.put("model-body.mustache", ".m"); apiTemplateFiles.put("api-header.mustache", ".h"); From 26a2290078726172bf3007071fb9288e3baaf582 Mon Sep 17 00:00:00 2001 From: hrachya Date: Thu, 28 May 2015 13:01:54 -0700 Subject: [PATCH 29/72] adding classPrefix, sourceFolder, projectName cli options to objc --- .../codegen/languages/ObjcClientCodegen.java | 51 +++++++++++++++---- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java index d1e227ce744..021ca0b3b21 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java @@ -1,6 +1,5 @@ package com.wordnik.swagger.codegen.languages; -import com.wordnik.swagger.util.Json; import com.wordnik.swagger.codegen.*; import com.wordnik.swagger.models.properties.*; @@ -10,7 +9,8 @@ import java.io.File; public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { protected Set foundationClasses = new HashSet(); protected String sourceFolder = "client"; - protected static String PREFIX = "SWG"; + protected String classPrefix = "SWG"; + protected String projectName = "swaggerClient"; public CodegenType getTag() { return CodegenType.CLIENT; @@ -34,12 +34,6 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { templateDir = "objc"; modelPackage = ""; - String appName = System.getProperty("appName"); - if(appName == null) { - appName = "swaggerClient"; - } - additionalProperties.put("projectName", appName); - defaultIncludes = new HashSet( Arrays.asList( "bool", @@ -111,7 +105,31 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { instantiationTypes.put("array", "NSMutableArray"); instantiationTypes.put("map", "NSMutableDictionary"); + + cliOptions.add(new CliOption("classPrefix", "class-prefix", true, "prefix for generated classes", true)); + cliOptions.add(new CliOption("sourceFolder", "source-folder", true, "source folder for generated code", true)); + cliOptions.add(new CliOption("projectName", "project-name", true, "name of the Xcode project in generated Podfile", true)); + } + @Override + public void processOpts() { + super.processOpts(); + + if(additionalProperties.containsKey("sourceFolder")) { + this.setSourceFolder((String)additionalProperties.get("sourceFolder")); + } + + if(additionalProperties.containsKey("classPrefix")) { + this.setClassPrefix((String)additionalProperties.get("classPrefix")); + } + + if(additionalProperties.containsKey("projectName")) { + this.setProjectName((String)additionalProperties.get("projectName")); + } + else{ + additionalProperties.put("projectName", projectName); + } + supportingFiles.add(new SupportingFile("SWGObject.h", sourceFolder, "SWGObject.h")); supportingFiles.add(new SupportingFile("SWGObject.m", sourceFolder, "SWGObject.m")); supportingFiles.add(new SupportingFile("SWGQueryParamCollection.h", sourceFolder, "SWGQueryParamCollection.h")); @@ -220,7 +238,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { } // custom classes else { - return PREFIX + camelize(type); + return classPrefix + camelize(type); } } @@ -266,11 +284,11 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String toApiName(String name) { - return PREFIX + camelize(name) + "Api"; + return classPrefix + camelize(name) + "Api"; } public String toApiFilename(String name) { - return PREFIX + camelize(name) + "Api"; + return classPrefix + camelize(name) + "Api"; } @Override @@ -313,4 +331,15 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { return camelize(operationId, true); } + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } + + public void setClassPrefix(String classPrefix) { + this.classPrefix = classPrefix; + } + + public void setProjectName(String projectName) { + this.projectName = projectName; + } } From c5a7800ec61fa52feec9e5793b0cb358bc85a19a Mon Sep 17 00:00:00 2001 From: hrachya Date: Thu, 28 May 2015 13:02:30 -0700 Subject: [PATCH 30/72] fixing typo --- modules/swagger-codegen/src/main/java/config/ConfigParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/java/config/ConfigParser.java b/modules/swagger-codegen/src/main/java/config/ConfigParser.java index df2b37c2923..019061faa33 100644 --- a/modules/swagger-codegen/src/main/java/config/ConfigParser.java +++ b/modules/swagger-codegen/src/main/java/config/ConfigParser.java @@ -15,7 +15,7 @@ public class ConfigParser { public static Config read(String location) { - System.out.println("reading cofig from " + location); + System.out.println("reading config from " + location); ObjectMapper mapper = new ObjectMapper(); From 08647b337fcecc4343520f339490752d84dff9c4 Mon Sep 17 00:00:00 2001 From: hrachya Date: Thu, 28 May 2015 13:08:52 -0700 Subject: [PATCH 31/72] fixing property name --- .../main/java/com/wordnik/swagger/codegen/DefaultCodegen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java index f7ec12b2c94..7a689164449 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java @@ -85,7 +85,7 @@ public class DefaultCodegen { public void processOpts(){ if(additionalProperties.containsKey("templateDir")) { - this.setTemplateDir((String)additionalProperties.get("t")); + this.setTemplateDir((String)additionalProperties.get("templateDir")); } if(additionalProperties.containsKey("modelPackage")) { From 1f360961e0bff365b3c0ad3f19a8e9f9c8829c5e Mon Sep 17 00:00:00 2001 From: hrachya Date: Thu, 28 May 2015 14:55:36 -0700 Subject: [PATCH 32/72] Simplifying CliOption class --- .../wordnik/swagger/codegen/CliOption.java | 40 ++++++------------- .../swagger/codegen/DefaultCodegen.java | 4 +- .../codegen/languages/JavaClientCodegen.java | 10 ++--- .../codegen/languages/ObjcClientCodegen.java | 6 +-- 4 files changed, 22 insertions(+), 38 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java index 837759b9d2f..4294d097116 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java @@ -5,40 +5,24 @@ */ package com.wordnik.swagger.codegen; -import org.apache.commons.cli.Option; +public class CliOption { + private final String opt; + private String description; -public class CliOption extends Option { - - private Boolean langSpecific = false; - - public CliOption(String opt, String description) throws IllegalArgumentException { - super(opt, description); + public CliOption(String opt, String description) { + this.opt = opt; + this.description = description; } - public CliOption(String opt, boolean hasArg, String description) throws IllegalArgumentException { - super(opt, hasArg, description); + public String getOpt() { + return opt; } - public CliOption(String opt, String longOpt, boolean hasArg, String description) throws IllegalArgumentException { - super(opt, longOpt, hasArg, description); + public String getDescription() { + return description; } - public CliOption(String opt, String description, Boolean langSpecific) throws IllegalArgumentException { - this(opt, description); - this.langSpecific = langSpecific; - } - - public CliOption(String opt, boolean hasArg, String description, Boolean langSpecific) throws IllegalArgumentException { - this(opt, hasArg, description); - this.langSpecific = langSpecific; - } - - public CliOption(String opt, String longOpt, boolean hasArg, String description, Boolean langSpecific) throws IllegalArgumentException { - this(opt, longOpt, hasArg, description); - this.langSpecific = langSpecific; - } - - public Boolean isLangSpecific() { - return langSpecific; + public void setDescription(String description) { + this.description = description; } } diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java index 7a689164449..d7788ef8865 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java @@ -303,8 +303,8 @@ public class DefaultCodegen { importMapping.put("LocalDate", "org.joda.time.*"); importMapping.put("LocalTime", "org.joda.time.*"); - cliOptions.add(new CliOption("modelPackage", "model-package", true, "Package for generated models")); - cliOptions.add(new CliOption("apiPackage", "api-package", true, "Package for generated api classes")); + cliOptions.add(new CliOption("modelPackage", "package for generated models")); + cliOptions.add(new CliOption("apiPackage", "package for generated api classes")); } diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java index 622e1322a1d..736b533ebc6 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java @@ -59,11 +59,11 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { instantiationTypes.put("array", "ArrayList"); instantiationTypes.put("map", "HashMap"); - cliOptions.add(new CliOption("invokerPackage", "invoker-package", true, "Root package for generated code", true)); - cliOptions.add(new CliOption("groupId", "group-id", true, "groupId in pom.xml", true)); - cliOptions.add(new CliOption("artifactId", "artifact-id", true, "groupId in pom.xml", true)); - cliOptions.add(new CliOption("artifactVersion", "artifact-version", true, "artifact version in pom.xml", true)); - cliOptions.add(new CliOption("sourceFolder", "source-folder", true, "Source folder for generated code", true)); + cliOptions.add(new CliOption("invokerPackage", "root package for generated code")); + cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); + cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); + cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); + cliOptions.add(new CliOption("sourceFolder", "source folder for generated code")); } @Override diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java index 021ca0b3b21..75d33511a9e 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java @@ -106,9 +106,9 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { instantiationTypes.put("array", "NSMutableArray"); instantiationTypes.put("map", "NSMutableDictionary"); - cliOptions.add(new CliOption("classPrefix", "class-prefix", true, "prefix for generated classes", true)); - cliOptions.add(new CliOption("sourceFolder", "source-folder", true, "source folder for generated code", true)); - cliOptions.add(new CliOption("projectName", "project-name", true, "name of the Xcode project in generated Podfile", true)); + cliOptions.add(new CliOption("classPrefix", "prefix for generated classes")); + cliOptions.add(new CliOption("sourceFolder", "source folder for generated code")); + cliOptions.add(new CliOption("projectName", "name of the Xcode project in generated Podfile")); } @Override From ba7025d54bd8f7dad69d808b125c50e679631463 Mon Sep 17 00:00:00 2001 From: hrachya Date: Thu, 28 May 2015 15:02:32 -0700 Subject: [PATCH 33/72] Adding config-help command --- .../swagger/codegen/SwaggerCodegen.java | 4 +- .../swagger/codegen/cmd/ConfigHelp.java | 54 +++++++++++++++++++ .../wordnik/swagger/codegen/cmd/Generate.java | 4 +- 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/ConfigHelp.java diff --git a/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/SwaggerCodegen.java b/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/SwaggerCodegen.java index c8c718fb67b..f2c794776ce 100644 --- a/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/SwaggerCodegen.java +++ b/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/SwaggerCodegen.java @@ -1,5 +1,6 @@ package com.wordnik.swagger.codegen; +import com.wordnik.swagger.codegen.cmd.ConfigHelp; import com.wordnik.swagger.codegen.cmd.Generate; import com.wordnik.swagger.codegen.cmd.Langs; import com.wordnik.swagger.codegen.cmd.Meta; @@ -27,7 +28,8 @@ public class SwaggerCodegen { Generate.class, Meta.class, Langs.class, - Help.class + Help.class, + ConfigHelp.class ); builder.build().parse(args).run(); diff --git a/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/ConfigHelp.java b/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/ConfigHelp.java new file mode 100644 index 00000000000..6934bcf702e --- /dev/null +++ b/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/ConfigHelp.java @@ -0,0 +1,54 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wordnik.swagger.codegen.cmd; + +import com.wordnik.swagger.codegen.CliOption; +import com.wordnik.swagger.codegen.CodegenConfig; +import io.airlift.airline.Command; +import io.airlift.airline.Option; +import java.util.ServiceLoader; +import static java.util.ServiceLoader.load; + +@Command(name = "config-help", description = "Config help for chosen lang") +public class ConfigHelp implements Runnable { + + @Option(name = {"-l", "--lang"}, title = "language", required = true, + description = "language to get config help for") + private String lang; + + @Override + public void run() { + System.out.println(); + CodegenConfig config = forName(lang); + System.out.println("CONFIG OPTIONS"); + for (CliOption langCliOption : config.cliOptions()) { + System.out.println("\t" + langCliOption.getOpt()); + System.out.println("\t " + langCliOption.getDescription()); + System.out.println(); + } + } + + /** + * Tries to load config class with SPI first, then with class name directly from classpath + * @param name name of config, or full qualified class name in classpath + * @return config class + */ + private static CodegenConfig forName(String name) { + ServiceLoader loader = load(CodegenConfig.class); + for (CodegenConfig config : loader) { + if (config.getName().equals(name)) { + return config; + } + } + + // else try to load directly + try { + return (CodegenConfig) Class.forName(name).newInstance(); + } catch (Exception e) { + throw new RuntimeException("Can't load config class with name ".concat(name), e); + } + } +} diff --git a/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/Generate.java b/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/Generate.java index 9bd2b5e0c24..3485eb8dd24 100644 --- a/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/Generate.java +++ b/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/Generate.java @@ -61,7 +61,9 @@ public class Generate implements Runnable { "the format of name=value,name=value") private String systemProperties; - @Option( name= {"-c", "--config"}, title = "configuration file", description = "path to json configuration file") + @Option( name= {"-c", "--config"}, title = "configuration file", description = "Path to json configuration file. " + + "File content should be in a json format {\"optionKey\":\"optionValue\", \"optionKey1\":\"optionValue1\"...} " + + "Supported options can be different for each language. Run config-help -l {lang} command for language specific config options.") private String configFile; @Override From 95813714a517c4b882292059f30fcf3395000251 Mon Sep 17 00:00:00 2001 From: xhh Date: Fri, 22 May 2015 21:34:11 +0800 Subject: [PATCH 34/72] Add support of HTTP basic and API key auth to Ruby codegen --- .../src/main/resources/ruby/swagger.mustache | 6 +-- .../ruby/swagger/configuration.mustache | 6 ++- .../resources/ruby/swagger/request.mustache | 44 ++++++++++------ .../client/petstore/ruby/spec/request_spec.rb | 51 +++---------------- 4 files changed, 41 insertions(+), 66 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/ruby/swagger.mustache b/modules/swagger-codegen/src/main/resources/ruby/swagger.mustache index 750e6ac5155..dd2f630a8c9 100644 --- a/modules/swagger-codegen/src/main/resources/ruby/swagger.mustache +++ b/modules/swagger-codegen/src/main/resources/ruby/swagger.mustache @@ -16,9 +16,9 @@ module {{moduleName}} # # @example # Swagger.configure do |config| - # config.api_key = '1234567890abcdef' # required - # config.username = 'wordlover' # optional, but needed for user-related functions - # config.password = 'i<3words' # optional, but needed for user-related functions + # config.api_key['api_key'] = '1234567890abcdef' # api key authentication + # config.username = 'wordlover' # http basic authentication + # config.password = 'i<3words' # http basic authentication # config.format = 'json' # optional, defaults to 'json' # end # diff --git a/modules/swagger-codegen/src/main/resources/ruby/swagger/configuration.mustache b/modules/swagger-codegen/src/main/resources/ruby/swagger/configuration.mustache index e780a9c8e7d..e6479797920 100644 --- a/modules/swagger-codegen/src/main/resources/ruby/swagger/configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/ruby/swagger/configuration.mustache @@ -1,8 +1,8 @@ module {{moduleName}} module Swagger class Configuration - attr_accessor :format, :api_key, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent - + attr_accessor :format, :api_key, :api_key_prefix, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent + # Defaults go in here.. def initialize @format = 'json' @@ -13,6 +13,8 @@ module {{moduleName}} @inject_format = false @force_ending_format = false @camelize_params = true + @api_key = {} + @api_key_prefix = {} end end end diff --git a/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache b/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache index 14718bb6b3c..1e04b92e23e 100644 --- a/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache +++ b/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache @@ -13,24 +13,14 @@ module {{moduleName}} attributes[:format] ||= Swagger.configuration.format attributes[:params] ||= {} + update_params_for_auth(attributes) + # Set default headers default_headers = { 'Content-Type' => "application/#{attributes[:format].downcase}", - :api_key => Swagger.configuration.api_key, 'User-Agent' => Swagger.configuration.user_agent } - # api_key from headers hash trumps the default, even if its value is blank - if attributes[:headers].present? && attributes[:headers].has_key?(:api_key) - default_headers.delete(:api_key) - end - - # api_key from params hash trumps all others (headers and default_headers) - if attributes[:params].present? && attributes[:params].has_key?(:api_key) - default_headers.delete(:api_key) - attributes[:headers].delete(:api_key) if attributes[:headers].present? - end - # Merge argument headers into defaults attributes[:headers] = default_headers.merge(attributes[:headers] || {}) @@ -46,6 +36,31 @@ module {{moduleName}} end end + def update_params_for_auth(attributes) + (attributes[:auth_names] || []).each do |auth_name| + case auth_name + {{#authMethods}} + when '{{name}}' + {{#isApiKey}}{{#isKeyInHeader}}attributes[:headers] ||= {} + attributes[:headers]['{{keyParamName}}'] = get_api_key_with_prefix('{{keyParamName}}'){{/isKeyInHeader}}{{#isKeyInQuery}}attributes[:params] ||= {} + attributes[:params]['{{keyParamName}}'] = get_api_key_with_prefix('{{keyParamName}}'){{/isKeyInQuery}}{{/isApiKey}} + {{#isBasic}}attributes[:headers] ||= {} + http_auth_header = 'Basic ' + ["#{Swagger.configuration.username}:#{Swagger.configuration.password}"].pack('m').delete("\r\n") + attributes[:headers]['Authorization'] = http_auth_header{{/isBasic}} + {{#isOAuth}}# TODO: support oauth{{/isOAuth}} + {{/authMethods}} + end + end + end + + def get_api_key_with_prefix(param_name) + if Swagger.configuration.api_key_prefix[param_name].present? + "#{Swagger.configuration.api_key_prefix[param_name]} #{Swagger.configuration.api_key[param_name]}" + else + Swagger.configuration.api_key[param_name] + end + end + # Construct a base URL def url(options = {}) u = Addressable::URI.new( @@ -58,9 +73,6 @@ module {{moduleName}} # Drop trailing question mark, if present u.sub! /\?$/, '' - # Obfuscate API key? - u.sub! /api\_key=\w+/, 'api_key=YOUR_API_KEY' if options[:obfuscated] - u end @@ -129,7 +141,7 @@ module {{moduleName}} next if self.path.include? "{#{key}}" # skip path params next if value.blank? && value.class != FalseClass # skip empties if Swagger.configuration.camelize_params - key = key.to_s.camelize(:lower).to_sym unless key.to_sym == :api_key # api_key is not a camelCased param + key = key.to_s.camelize(:lower).to_sym end query_values[key] = value.to_s end diff --git a/samples/client/petstore/ruby/spec/request_spec.rb b/samples/client/petstore/ruby/spec/request_spec.rb index 8856a0cf315..583ae591539 100644 --- a/samples/client/petstore/ruby/spec/request_spec.rb +++ b/samples/client/petstore/ruby/spec/request_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe SwaggerClient::Swagger::Request do - before(:each) do + before(:each) do SwaggerClient::Swagger.configure do |config| inject_format = true config.api_key = 'special-key' @@ -22,7 +22,7 @@ describe SwaggerClient::Swagger::Request do it "sets default response format to json" do @request.format.should == 'json' end - + it "allows params to be nil" do @request = SwaggerClient::Swagger::Request.new(@default_http_method, @default_path, :params => nil) @request.query_string.should == "" @@ -55,7 +55,7 @@ describe SwaggerClient::Swagger::Request do end end - + describe "body" do it "camelCases parameters" do @@ -67,7 +67,7 @@ describe SwaggerClient::Swagger::Request do })) @request.body.keys.should == [:badDog, :goodDog] end - + end describe "path" do @@ -140,7 +140,7 @@ describe SwaggerClient::Swagger::Request do @request.query_string.should =~ /\?limit=100/ @request.url.should =~ /\?limit=100/ end - + it "camelCases parameters" do @request = SwaggerClient::Swagger::Request.new(@default_http_method, @default_path, @default_params.merge({ :params => { @@ -150,51 +150,12 @@ describe SwaggerClient::Swagger::Request do })) @request.query_string.should == "?badDog=bud&goodDog=dud" end - + it "converts boolean values to their string representation" do params = {:stringy => "fish", :truthy => true, :falsey => false} @request = SwaggerClient::Swagger::Request.new(:get, 'fakeMethod', :params => params) @request.query_string.should == "?falsey=false&stringy=fish&truthy=true" end - - end - - describe "API key" do - - it "is inferred from the Swagger base configuration by default" do - SwaggerClient::Swagger.configure {|c| c.api_key = "xyz" } - SwaggerClient::Swagger::Request.new(:get, "word/json").headers[:api_key].should == "xyz" - end - - it "can be obfuscated for public display" do - @request = SwaggerClient::Swagger::Request.new(:get, "words/fancy", @default_params.merge({ - :params => { - :word => "dog", - :api_key => "123456" - } - })) - - @request.url.should =~ /api\_key=123456/ - @request.url(:obfuscated => true).should =~ /api\_key=YOUR\_API\_KEY/ - end - - it "allows a key in the params to override the configuration-level key, even if it's blank" do - SwaggerClient::Swagger.configure {|c| c.api_key = "abc" } - @request_with_key = SwaggerClient::Swagger::Request.new(:get, "word/json", :params => {:api_key => "jkl"}) - @request_with_key.headers[:api_key].should be_nil - @request_with_key.params[:api_key].should == "jkl" - - @request_without_key = SwaggerClient::Swagger::Request.new(:get, "word/json", :params => {:api_key => nil}) - @request_without_key.headers[:api_key].should be_nil - @request_without_key.params[:api_key].should be_nil - end - - it "allows a key in the headers to override the configuration-level key, even if it's blank" do - SwaggerClient::Swagger.configure {|c| c.api_key = "hij" } - SwaggerClient::Swagger::Request.new(:get, "word/json").headers[:api_key].should == "hij" - SwaggerClient::Swagger::Request.new(:get, "word/json", :headers => {:api_key => "jkl"}).headers[:api_key].should == "jkl" - SwaggerClient::Swagger::Request.new(:get, "word/json", :headers => {:api_key => nil}).headers[:api_key].should be_nil - end end From e52694cde0e7b938b6c94dba9ccfb9dd67995905 Mon Sep 17 00:00:00 2001 From: xhh Date: Sat, 23 May 2015 09:41:03 +0800 Subject: [PATCH 35/72] Regenerate Ruby Petstore sample --- .../ruby/lib/swagger_client/swagger.rb | 6 +-- .../swagger_client/swagger/configuration.rb | 6 ++- .../lib/swagger_client/swagger/request.rb | 46 ++++++++++++------- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/samples/client/petstore/ruby/lib/swagger_client/swagger.rb b/samples/client/petstore/ruby/lib/swagger_client/swagger.rb index 278db36e4ca..2e2632c169d 100644 --- a/samples/client/petstore/ruby/lib/swagger_client/swagger.rb +++ b/samples/client/petstore/ruby/lib/swagger_client/swagger.rb @@ -16,9 +16,9 @@ module SwaggerClient # # @example # Swagger.configure do |config| - # config.api_key = '1234567890abcdef' # required - # config.username = 'wordlover' # optional, but needed for user-related functions - # config.password = 'i<3words' # optional, but needed for user-related functions + # config.api_key['api_key'] = '1234567890abcdef' # api key authentication + # config.username = 'wordlover' # http basic authentication + # config.password = 'i<3words' # http basic authentication # config.format = 'json' # optional, defaults to 'json' # end # diff --git a/samples/client/petstore/ruby/lib/swagger_client/swagger/configuration.rb b/samples/client/petstore/ruby/lib/swagger_client/swagger/configuration.rb index 51f9539a9ab..91cdb66e099 100644 --- a/samples/client/petstore/ruby/lib/swagger_client/swagger/configuration.rb +++ b/samples/client/petstore/ruby/lib/swagger_client/swagger/configuration.rb @@ -1,8 +1,8 @@ module SwaggerClient module Swagger class Configuration - attr_accessor :format, :api_key, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent - + attr_accessor :format, :api_key, :api_key_prefix, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent + # Defaults go in here.. def initialize @format = 'json' @@ -13,6 +13,8 @@ module SwaggerClient @inject_format = false @force_ending_format = false @camelize_params = true + @api_key = {} + @api_key_prefix = {} end end end diff --git a/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb b/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb index d5f266267da..0dd1757167c 100644 --- a/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb +++ b/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb @@ -13,24 +13,14 @@ module SwaggerClient attributes[:format] ||= Swagger.configuration.format attributes[:params] ||= {} + update_params_for_auth(attributes) + # Set default headers default_headers = { 'Content-Type' => "application/#{attributes[:format].downcase}", - :api_key => Swagger.configuration.api_key, 'User-Agent' => Swagger.configuration.user_agent } - # api_key from headers hash trumps the default, even if its value is blank - if attributes[:headers].present? && attributes[:headers].has_key?(:api_key) - default_headers.delete(:api_key) - end - - # api_key from params hash trumps all others (headers and default_headers) - if attributes[:params].present? && attributes[:params].has_key?(:api_key) - default_headers.delete(:api_key) - attributes[:headers].delete(:api_key) if attributes[:headers].present? - end - # Merge argument headers into defaults attributes[:headers] = default_headers.merge(attributes[:headers] || {}) @@ -46,6 +36,33 @@ module SwaggerClient end end + def update_params_for_auth(attributes) + (attributes[:auth_names] || []).each do |auth_name| + case auth_name + + when 'api_key' + attributes[:headers] ||= {} + attributes[:headers]['api_key'] = get_api_key_with_prefix('api_key') + + + + when 'petstore_auth' + + + # TODO: support oauth + + end + end + end + + def get_api_key_with_prefix(param_name) + if Swagger.configuration.api_key_prefix[param_name].present? + "#{Swagger.configuration.api_key_prefix[param_name]} #{Swagger.configuration.api_key[param_name]}" + else + Swagger.configuration.api_key[param_name] + end + end + # Construct a base URL def url(options = {}) u = Addressable::URI.new( @@ -58,9 +75,6 @@ module SwaggerClient # Drop trailing question mark, if present u.sub! /\?$/, '' - # Obfuscate API key? - u.sub! /api\_key=\w+/, 'api_key=YOUR_API_KEY' if options[:obfuscated] - u end @@ -129,7 +143,7 @@ module SwaggerClient next if self.path.include? "{#{key}}" # skip path params next if value.blank? && value.class != FalseClass # skip empties if Swagger.configuration.camelize_params - key = key.to_s.camelize(:lower).to_sym unless key.to_sym == :api_key # api_key is not a camelCased param + key = key.to_s.camelize(:lower).to_sym end query_values[key] = value.to_s end From 623a1278cf6b1ff26814f14eed6519f6598041fa Mon Sep 17 00:00:00 2001 From: xhh Date: Sat, 23 May 2015 11:52:49 +0800 Subject: [PATCH 36/72] Add test case for API key auth --- .../src/main/resources/ruby/api.mustache | 5 ++-- .../resources/ruby/swagger/request.mustache | 23 ++++++++---------- .../ruby/lib/swagger_client/api/pet_api.rb | 24 ++++++++++++------- .../ruby/lib/swagger_client/api/store_api.rb | 12 ++++++---- .../ruby/lib/swagger_client/api/user_api.rb | 24 ++++++++++++------- .../lib/swagger_client/swagger/request.rb | 20 ++++++---------- .../client/petstore/ruby/spec/request_spec.rb | 24 ++++++++++++++++++- .../client/petstore/ruby/spec/spec_helper.rb | 2 +- 8 files changed, 84 insertions(+), 50 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/ruby/api.mustache b/modules/swagger-codegen/src/main/resources/ruby/api.mustache index e9f90087db1..3e1ac14014e 100644 --- a/modules/swagger-codegen/src/main/resources/ruby/api.mustache +++ b/modules/swagger-codegen/src/main/resources/ruby/api.mustache @@ -50,8 +50,9 @@ module {{moduleName}} {{/bodyParam}}{{#bodyParam}}post_body = Swagger::Request.object_to_http_body({{#required}}{{{paramName}}}{{/required}}{{^required}}opts[:'{{{paramName}}}']{{/required}}) {{/bodyParam}} - {{#returnType}}response = Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body - {{#returnContainer}}response.map {|response| {{/returnContainer}}obj = {{returnBaseType}}.new() and obj.build_from_hash(response){{#returnContainer}} }{{/returnContainer}}{{/returnType}}{{^returnType}}Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}] + {{#returnType}}response = Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make.body + {{#returnContainer}}response.map {|response| {{/returnContainer}}obj = {{returnBaseType}}.new() and obj.build_from_hash(response){{#returnContainer}} }{{/returnContainer}}{{/returnType}}{{^returnType}}Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil{{/returnType}} end {{/operation}} diff --git a/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache b/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache index 1e04b92e23e..07fa2035db2 100644 --- a/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache +++ b/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache @@ -5,7 +5,7 @@ module {{moduleName}} require 'addressable/uri' require 'typhoeus' - attr_accessor :host, :path, :format, :params, :body, :http_method, :headers, :form_params + attr_accessor :host, :path, :format, :params, :body, :http_method, :headers, :form_params, :auth_names # All requests must have an HTTP method and a path # Optionals parameters are :params, :headers, :body, :format, :host @@ -13,8 +13,6 @@ module {{moduleName}} attributes[:format] ||= Swagger.configuration.format attributes[:params] ||= {} - update_params_for_auth(attributes) - # Set default headers default_headers = { 'Content-Type' => "application/#{attributes[:format].downcase}", @@ -34,20 +32,19 @@ module {{moduleName}} attributes.each do |name, value| send("#{name.to_s.underscore.to_sym}=", value) end + + update_params_for_auth! end - def update_params_for_auth(attributes) - (attributes[:auth_names] || []).each do |auth_name| + def update_params_for_auth! + (@auth_names || []).each do |auth_name| case auth_name - {{#authMethods}} - when '{{name}}' - {{#isApiKey}}{{#isKeyInHeader}}attributes[:headers] ||= {} - attributes[:headers]['{{keyParamName}}'] = get_api_key_with_prefix('{{keyParamName}}'){{/isKeyInHeader}}{{#isKeyInQuery}}attributes[:params] ||= {} - attributes[:params]['{{keyParamName}}'] = get_api_key_with_prefix('{{keyParamName}}'){{/isKeyInQuery}}{{/isApiKey}} - {{#isBasic}}attributes[:headers] ||= {} + {{#authMethods}}when '{{name}}' + {{#isApiKey}}{{#isKeyInHeader}}@headers ||= {} + @headers['{{keyParamName}}'] = get_api_key_with_prefix('{{keyParamName}}'){{/isKeyInHeader}}{{#isKeyInQuery}}@params ||= {} + @params['{{keyParamName}}'] = get_api_key_with_prefix('{{keyParamName}}'){{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}@headers ||= {} http_auth_header = 'Basic ' + ["#{Swagger.configuration.username}:#{Swagger.configuration.password}"].pack('m').delete("\r\n") - attributes[:headers]['Authorization'] = http_auth_header{{/isBasic}} - {{#isOAuth}}# TODO: support oauth{{/isOAuth}} + @headers['Authorization'] = http_auth_header{{/isBasic}}{{#isOAuth}}# TODO: support oauth{{/isOAuth}} {{/authMethods}} end end diff --git a/samples/client/petstore/ruby/lib/swagger_client/api/pet_api.rb b/samples/client/petstore/ruby/lib/swagger_client/api/pet_api.rb index 40e5f1e3177..7bed9b47780 100644 --- a/samples/client/petstore/ruby/lib/swagger_client/api/pet_api.rb +++ b/samples/client/petstore/ruby/lib/swagger_client/api/pet_api.rb @@ -37,7 +37,8 @@ module SwaggerClient post_body = Swagger::Request.object_to_http_body(opts[:'body']) - Swagger::Request.new(:PUT, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = ['petstore_auth'] + Swagger::Request.new(:PUT, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end @@ -73,7 +74,8 @@ module SwaggerClient post_body = Swagger::Request.object_to_http_body(opts[:'body']) - Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = ['petstore_auth'] + Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end @@ -110,7 +112,8 @@ module SwaggerClient post_body = nil - response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body + auth_names = ['petstore_auth'] + response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make.body response.map {|response| obj = Pet.new() and obj.build_from_hash(response) } end @@ -147,7 +150,8 @@ module SwaggerClient post_body = nil - response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body + auth_names = ['petstore_auth'] + response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make.body response.map {|response| obj = Pet.new() and obj.build_from_hash(response) } end @@ -186,7 +190,8 @@ module SwaggerClient post_body = nil - response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body + auth_names = ['api_key', 'petstore_auth'] + response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make.body obj = Pet.new() and obj.build_from_hash(response) end @@ -229,7 +234,8 @@ module SwaggerClient post_body = nil - Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = ['petstore_auth'] + Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end @@ -270,7 +276,8 @@ module SwaggerClient post_body = nil - Swagger::Request.new(:DELETE, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = ['petstore_auth'] + Swagger::Request.new(:DELETE, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end @@ -313,7 +320,8 @@ module SwaggerClient post_body = nil - Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = ['petstore_auth'] + Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end end diff --git a/samples/client/petstore/ruby/lib/swagger_client/api/store_api.rb b/samples/client/petstore/ruby/lib/swagger_client/api/store_api.rb index 594c30a0775..010d170945b 100644 --- a/samples/client/petstore/ruby/lib/swagger_client/api/store_api.rb +++ b/samples/client/petstore/ruby/lib/swagger_client/api/store_api.rb @@ -36,7 +36,8 @@ module SwaggerClient post_body = nil - response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body + auth_names = ['api_key'] + response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make.body response.map {|response| obj = map.new() and obj.build_from_hash(response) } end @@ -72,7 +73,8 @@ module SwaggerClient post_body = Swagger::Request.object_to_http_body(opts[:'body']) - response = Swagger::Request.new(:POST, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body + auth_names = [] + response = Swagger::Request.new(:POST, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make.body obj = Order.new() and obj.build_from_hash(response) end @@ -111,7 +113,8 @@ module SwaggerClient post_body = nil - response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body + auth_names = [] + response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make.body obj = Order.new() and obj.build_from_hash(response) end @@ -150,7 +153,8 @@ module SwaggerClient post_body = nil - Swagger::Request.new(:DELETE, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = [] + Swagger::Request.new(:DELETE, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end end diff --git a/samples/client/petstore/ruby/lib/swagger_client/api/user_api.rb b/samples/client/petstore/ruby/lib/swagger_client/api/user_api.rb index 96fe0cabada..a3a57503b01 100644 --- a/samples/client/petstore/ruby/lib/swagger_client/api/user_api.rb +++ b/samples/client/petstore/ruby/lib/swagger_client/api/user_api.rb @@ -37,7 +37,8 @@ module SwaggerClient post_body = Swagger::Request.object_to_http_body(opts[:'body']) - Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = [] + Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end @@ -73,7 +74,8 @@ module SwaggerClient post_body = Swagger::Request.object_to_http_body(opts[:'body']) - Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = [] + Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end @@ -109,7 +111,8 @@ module SwaggerClient post_body = Swagger::Request.object_to_http_body(opts[:'body']) - Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = [] + Swagger::Request.new(:POST, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end @@ -148,7 +151,8 @@ module SwaggerClient post_body = nil - response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body + auth_names = [] + response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make.body obj = string.new() and obj.build_from_hash(response) end @@ -183,7 +187,8 @@ module SwaggerClient post_body = nil - Swagger::Request.new(:GET, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = [] + Swagger::Request.new(:GET, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end @@ -222,7 +227,8 @@ module SwaggerClient post_body = nil - response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body + auth_names = [] + response = Swagger::Request.new(:GET, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make.body obj = User.new() and obj.build_from_hash(response) end @@ -262,7 +268,8 @@ module SwaggerClient post_body = Swagger::Request.object_to_http_body(opts[:'body']) - Swagger::Request.new(:PUT, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = [] + Swagger::Request.new(:PUT, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end @@ -301,7 +308,8 @@ module SwaggerClient post_body = nil - Swagger::Request.new(:DELETE, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make + auth_names = [] + Swagger::Request.new(:DELETE, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make nil end end diff --git a/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb b/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb index 0dd1757167c..d063313f2d6 100644 --- a/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb +++ b/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb @@ -5,7 +5,7 @@ module SwaggerClient require 'addressable/uri' require 'typhoeus' - attr_accessor :host, :path, :format, :params, :body, :http_method, :headers, :form_params + attr_accessor :host, :path, :format, :params, :body, :http_method, :headers, :form_params, :auth_names # All requests must have an HTTP method and a path # Optionals parameters are :params, :headers, :body, :format, :host @@ -13,8 +13,6 @@ module SwaggerClient attributes[:format] ||= Swagger.configuration.format attributes[:params] ||= {} - update_params_for_auth(attributes) - # Set default headers default_headers = { 'Content-Type' => "application/#{attributes[:format].downcase}", @@ -34,21 +32,17 @@ module SwaggerClient attributes.each do |name, value| send("#{name.to_s.underscore.to_sym}=", value) end + + update_params_for_auth! end - def update_params_for_auth(attributes) - (attributes[:auth_names] || []).each do |auth_name| + def update_params_for_auth! + (@auth_names || []).each do |auth_name| case auth_name - when 'api_key' - attributes[:headers] ||= {} - attributes[:headers]['api_key'] = get_api_key_with_prefix('api_key') - - - + @headers ||= {} + @headers['api_key'] = get_api_key_with_prefix('api_key') when 'petstore_auth' - - # TODO: support oauth end diff --git a/samples/client/petstore/ruby/spec/request_spec.rb b/samples/client/petstore/ruby/spec/request_spec.rb index 583ae591539..49bbc5cdd1e 100644 --- a/samples/client/petstore/ruby/spec/request_spec.rb +++ b/samples/client/petstore/ruby/spec/request_spec.rb @@ -5,7 +5,7 @@ describe SwaggerClient::Swagger::Request do before(:each) do SwaggerClient::Swagger.configure do |config| inject_format = true - config.api_key = 'special-key' + config.api_key['api_key'] = 'special-key' config.host = 'petstore.swagger.io' config.base_path = '/v2' end @@ -159,4 +159,26 @@ describe SwaggerClient::Swagger::Request do end + describe "#update_params_for_auth!" do + it "sets header api-key parameter with prefix" do + SwaggerClient::Swagger.configure do |config| + inject_format = true + config.api_key_prefix['api_key'] = 'PREFIX' + end + @request.auth_names = ['api_key', 'unknown'] + @request.update_params_for_auth! + @request.headers['api_key'].should == 'PREFIX special-key' + end + + it "sets header api-key parameter without prefix" do + SwaggerClient::Swagger.configure do |config| + inject_format = true + config.api_key_prefix['api_key'] = nil + end + @request.auth_names = ['api_key', 'unknown'] + @request.update_params_for_auth! + @request.headers['api_key'].should == 'special-key' + end + end + end diff --git a/samples/client/petstore/ruby/spec/spec_helper.rb b/samples/client/petstore/ruby/spec/spec_helper.rb index 09012db2998..f9081d3fe08 100644 --- a/samples/client/petstore/ruby/spec/spec_helper.rb +++ b/samples/client/petstore/ruby/spec/spec_helper.rb @@ -38,7 +38,7 @@ end def configure_swagger SwaggerClient::Swagger.configure do |config| - config.api_key = 'special-key' + config.api_key['api_key'] = 'special-key' config.host = 'petstore.swagger.io' config.base_path = '/v2' end From a29c3abeb8a48a0d1b30f26f86bdccf7a07f3a68 Mon Sep 17 00:00:00 2001 From: xhh Date: Fri, 29 May 2015 12:05:47 +0800 Subject: [PATCH 37/72] Use File.separatorChar in Ruby generator, add comments --- .../codegen/languages/RubyClientCodegen.java | 16 ++++++++-------- .../main/resources/ruby/swagger/request.mustache | 3 +++ .../ruby/lib/swagger_client/swagger/request.rb | 3 +++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/RubyClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/RubyClientCodegen.java index 939c0eb0e0a..3ca7758b1a3 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/RubyClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/RubyClientCodegen.java @@ -36,7 +36,7 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { moduleName = generateModuleName(); modelPackage = gemName + "/models"; apiPackage = gemName + "/api"; - outputFolder = "generated-code/ruby"; + outputFolder = "generated-code" + File.separatorChar + "ruby"; modelTemplateFiles.put("model.mustache", ".rb"); apiTemplateFiles.put("api.mustache", ".rb"); templateDir = "ruby"; @@ -69,17 +69,17 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("List", "array"); typeMapping.put("map", "map"); - String baseFolder = "lib/" + gemName; - String swaggerFolder = baseFolder + "/swagger"; - String modelFolder = baseFolder + "/models"; + String baseFolder = "lib" + File.separatorChar + gemName; + String swaggerFolder = baseFolder + File.separatorChar + "swagger"; + String modelFolder = baseFolder + File.separatorChar + "models"; supportingFiles.add(new SupportingFile("swagger_client.gemspec.mustache", "", gemName + ".gemspec")); supportingFiles.add(new SupportingFile("swagger_client.mustache", "lib", gemName + ".rb")); supportingFiles.add(new SupportingFile("monkey.mustache", baseFolder, "monkey.rb")); supportingFiles.add(new SupportingFile("swagger.mustache", baseFolder, "swagger.rb")); - supportingFiles.add(new SupportingFile("swagger/request.mustache", swaggerFolder, "request.rb")); - supportingFiles.add(new SupportingFile("swagger/response.mustache", swaggerFolder, "response.rb")); - supportingFiles.add(new SupportingFile("swagger/version.mustache", swaggerFolder, "version.rb")); - supportingFiles.add(new SupportingFile("swagger/configuration.mustache", swaggerFolder, "configuration.rb")); + supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "request.mustache", swaggerFolder, "request.rb")); + supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "response.mustache", swaggerFolder, "response.rb")); + supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "version.mustache", swaggerFolder, "version.rb")); + supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "configuration.mustache", swaggerFolder, "configuration.rb")); supportingFiles.add(new SupportingFile("base_object.mustache", modelFolder, "base_object.rb")); } diff --git a/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache b/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache index 07fa2035db2..85270369763 100644 --- a/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache +++ b/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache @@ -36,6 +36,7 @@ module {{moduleName}} update_params_for_auth! end + # Update hearder and query params based on authentication settings. def update_params_for_auth! (@auth_names || []).each do |auth_name| case auth_name @@ -50,6 +51,8 @@ module {{moduleName}} end end + # Get API key (with prefix if set). + # @param [String] param_name the parameter name of API key auth def get_api_key_with_prefix(param_name) if Swagger.configuration.api_key_prefix[param_name].present? "#{Swagger.configuration.api_key_prefix[param_name]} #{Swagger.configuration.api_key[param_name]}" diff --git a/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb b/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb index d063313f2d6..a595d6ab7a1 100644 --- a/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb +++ b/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb @@ -36,6 +36,7 @@ module SwaggerClient update_params_for_auth! end + # Update hearder and query params based on authentication settings. def update_params_for_auth! (@auth_names || []).each do |auth_name| case auth_name @@ -49,6 +50,8 @@ module SwaggerClient end end + # Get API key (with prefix if set). + # @param [String] param_name the parameter name of API key auth def get_api_key_with_prefix(param_name) if Swagger.configuration.api_key_prefix[param_name].present? "#{Swagger.configuration.api_key_prefix[param_name]} #{Swagger.configuration.api_key[param_name]}" From ac134c0afa9e50b27fea9df519df99bb55fc7784 Mon Sep 17 00:00:00 2001 From: xhh Date: Tue, 26 May 2015 16:05:47 +0800 Subject: [PATCH 38/72] Make ApiClient more pluggable for Java - Rename ApiInvoker to ApiClient - Make ApiClient pluggable by allowing setting the ApiClient field of API classes - Introduce a Configuration class, containing the default ApiClient (which is also customizable) - Move basePath from API class to ApiClient - Change static methods in ApiClient to instance level --- .../codegen/languages/JavaClientCodegen.java | 10 +- ...apiInvoker.mustache => ApiClient.mustache} | 106 +++++++++--------- .../resources/Java/Configuration.mustache | 13 +++ .../src/main/resources/Java/api.mustache | 36 +++--- 4 files changed, 95 insertions(+), 70 deletions(-) rename modules/swagger-codegen/src/main/resources/Java/{apiInvoker.mustache => ApiClient.mustache} (77%) create mode 100644 modules/swagger-codegen/src/main/resources/Java/Configuration.mustache diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java index 7c0ac7422ff..0881b2035f8 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java @@ -51,11 +51,13 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { additionalProperties.put("artifactVersion", artifactVersion); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); - supportingFiles.add(new SupportingFile("apiInvoker.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.java")); - supportingFiles.add(new SupportingFile("JsonUtil.mustache", + supportingFiles.add(new SupportingFile("ApiClient.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiClient.java")); + supportingFiles.add(new SupportingFile("Configuration.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "Configuration.java")); + supportingFiles.add(new SupportingFile("JsonUtil.mustache", (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java")); - supportingFiles.add(new SupportingFile("apiException.mustache", + supportingFiles.add(new SupportingFile("apiException.mustache", (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java")); languageSpecificPrimitives = new HashSet( diff --git a/modules/swagger-codegen/src/main/resources/Java/apiInvoker.mustache b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache similarity index 77% rename from modules/swagger-codegen/src/main/resources/Java/apiInvoker.mustache rename to modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache index c30ba4cdd12..cd0805d775f 100644 --- a/modules/swagger-codegen/src/main/resources/Java/apiInvoker.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache @@ -29,65 +29,82 @@ import java.net.URLEncoder; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.text.DateFormat; import java.text.SimpleDateFormat; import java.text.ParseException; -public class ApiInvoker { - private static ApiInvoker INSTANCE = new ApiInvoker(); +public class ApiClient { private Map hostMap = new HashMap(); private Map defaultHeaderMap = new HashMap(); private boolean isDebug = false; + private String basePath = "{{basePath}}"; - /** - * ISO 8601 date time format. - * @see https://en.wikipedia.org/wiki/ISO_8601 - */ - public static final SimpleDateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + private DateFormat dateFormat; + private DateFormat datetimeFormat; - /** - * ISO 8601 date format. - * @see https://en.wikipedia.org/wiki/ISO_8601 - */ - public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); + public ApiClient() { + // Use ISO 8601 format for date and datetime. + // See https://en.wikipedia.org/wiki/ISO_8601 + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + this.datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - static { // Use UTC as the default time zone. - DATE_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); - DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + this.datetimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); // Set default User-Agent. setUserAgent("Java-Swagger"); } - public static void setUserAgent(String userAgent) { - INSTANCE.addDefaultHeader("User-Agent", userAgent); + public String getBasePath() { + return basePath; } - public static Date parseDateTime(String str) { + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + public ApiClient enableDebug() { + isDebug = true; + return this; + } + + public Date parseDateTime(String str) { try { - return DATE_TIME_FORMAT.parse(str); + return datetimeFormat.parse(str); } catch (java.text.ParseException e) { throw new RuntimeException(e); } } - public static Date parseDate(String str) { + public Date parseDate(String str) { try { - return DATE_FORMAT.parse(str); + return dateFormat.parse(str); } catch (java.text.ParseException e) { throw new RuntimeException(e); } } - public static String formatDateTime(Date datetime) { - return DATE_TIME_FORMAT.format(datetime); + public String formatDateTime(Date datetime) { + return datetimeFormat.format(datetime); } - public static String formatDate(Date date) { - return DATE_FORMAT.format(date); + public String formatDate(Date date) { + return dateFormat.format(date); } - public static String parameterToString(Object param) { + public String parameterToString(Object param) { if (param == null) { return ""; } else if (param instanceof Date) { @@ -105,17 +122,6 @@ public class ApiInvoker { return String.valueOf(param); } } - public void enableDebug() { - isDebug = true; - } - - public static ApiInvoker getInstance() { - return INSTANCE; - } - - public void addDefaultHeader(String key, String value) { - defaultHeaderMap.put(key, value); - } public String escapeString(String str) { try{ @@ -126,7 +132,7 @@ public class ApiInvoker { } } - public static Object deserialize(String json, String containerType, Class cls) throws ApiException { + public Object deserialize(String json, String containerType, Class cls) throws ApiException { if(null != containerType) { containerType = containerType.toLowerCase(); } @@ -151,7 +157,7 @@ public class ApiInvoker { } } - public static String serialize(Object obj) throws ApiException { + public String serialize(Object obj) throws ApiException { try { if (obj != null) return JsonUtil.getJsonMapper().writeValueAsString(obj); @@ -163,8 +169,8 @@ public class ApiInvoker { } } - public String invokeAPI(String host, String path, String method, Map queryParams, Object body, Map headerParams, Map formParams, String contentType) throws ApiException { - Client client = getClient(host); + public String invokeAPI(String path, String method, Map queryParams, Object body, Map headerParams, Map formParams, String contentType) throws ApiException { + Client client = getClient(); StringBuilder b = new StringBuilder(); @@ -180,7 +186,7 @@ public class ApiInvoker { } String querystring = b.toString(); - Builder builder = client.resource(host + path + querystring).accept("application/json"); + Builder builder = client.resource(basePath + path + querystring).accept("application/json"); for(String key : headerParams.keySet()) { builder = builder.header(key, headerParams.get(key)); } @@ -236,6 +242,7 @@ public class ApiInvoker { else { throw new ApiException(500, "unknown method type " + method); } + if(response.getClientResponseStatus() == ClientResponse.Status.NO_CONTENT) { return null; } @@ -267,8 +274,8 @@ public class ApiInvoker { StringBuilder formParamBuilder = new StringBuilder(); for (Entry param : formParams.entrySet()) { - String keyStr = ApiInvoker.parameterToString(param.getKey()); - String valueStr = ApiInvoker.parameterToString(param.getValue()); + String keyStr = parameterToString(param.getKey()); + String valueStr = parameterToString(param.getValue()); try { formParamBuilder.append(URLEncoder.encode(keyStr, "utf8")) @@ -287,14 +294,13 @@ public class ApiInvoker { return encodedFormParams; } - - private Client getClient(String host) { - if(!hostMap.containsKey(host)) { + private Client getClient() { + if(!hostMap.containsKey(basePath)) { Client client = Client.create(); if(isDebug) client.addFilter(new LoggingFilter()); - hostMap.put(host, client); + hostMap.put(basePath, client); } - return hostMap.get(host); + return hostMap.get(basePath); } -} \ No newline at end of file +} diff --git a/modules/swagger-codegen/src/main/resources/Java/Configuration.mustache b/modules/swagger-codegen/src/main/resources/Java/Configuration.mustache new file mode 100644 index 00000000000..ce1e6dec1ce --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Java/Configuration.mustache @@ -0,0 +1,13 @@ +package {{invokerPackage}}; + +public class Configuration { + private static ApiClient defaultApiClient = new ApiClient(); + + public static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + public static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/modules/swagger-codegen/src/main/resources/Java/api.mustache b/modules/swagger-codegen/src/main/resources/Java/api.mustache index 78bac41d9d6..6e6a7a79940 100644 --- a/modules/swagger-codegen/src/main/resources/Java/api.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/api.mustache @@ -1,7 +1,8 @@ package {{package}}; import {{invokerPackage}}.ApiException; -import {{invokerPackage}}.ApiInvoker; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.Configuration; import {{modelPackage}}.*; @@ -21,19 +22,22 @@ import java.util.HashMap; {{#operations}} public class {{classname}} { - String basePath = "{{basePath}}"; - ApiInvoker apiInvoker = ApiInvoker.getInstance(); + private ApiClient apiClient; - public ApiInvoker getInvoker() { - return apiInvoker; + public {{classname}}() { + this(Configuration.getDefaultApiClient()); } - public void setBasePath(String basePath) { - this.basePath = basePath; + public {{classname}}(ApiClient apiClient) { + this.apiClient = apiClient; } - public String getBasePath() { - return basePath; + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; } {{#operation}} @@ -54,7 +58,7 @@ public class {{classname}} { // create path and map variables String path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}} - .replaceAll("\\{" + "{{paramName}}" + "\\}", apiInvoker.escapeString({{{paramName}}}.toString())){{/pathParams}}; + .replaceAll("\\{" + "{{paramName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; // query params Map queryParams = new HashMap(); @@ -62,9 +66,9 @@ public class {{classname}} { Map formParams = new HashMap(); {{#queryParams}}if ({{paramName}} != null) - queryParams.put("{{baseName}}", ApiInvoker.parameterToString({{paramName}})); + queryParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/queryParams}} - {{#headerParams}}headerParams.put("{{baseName}}", ApiInvoker.parameterToString({{paramName}})); + {{#headerParams}}headerParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/headerParams}} String[] contentTypes = { {{#consumes}}"{{mediaType}}"{{#hasMore}},{{/hasMore}}{{/consumes}} @@ -77,7 +81,7 @@ public class {{classname}} { FormDataMultiPart mp = new FormDataMultiPart(); {{#formParams}}{{#notFile}} hasFields = true; - mp.field("{{baseName}}", ApiInvoker.parameterToString({{paramName}}), MediaType.MULTIPART_FORM_DATA_TYPE); + mp.field("{{baseName}}", apiClient.parameterToString({{paramName}}), MediaType.MULTIPART_FORM_DATA_TYPE); {{/notFile}}{{#isFile}} hasFields = true; mp.field("{{baseName}}", file.getName()); @@ -87,14 +91,14 @@ public class {{classname}} { postBody = mp; } else { - {{#formParams}}{{#notFile}}formParams.put("{{baseName}}", ApiInvoker.parameterToString({{paramName}}));{{/notFile}} + {{#formParams}}{{#notFile}}formParams.put("{{baseName}}", apiClient.parameterToString({{paramName}}));{{/notFile}} {{/formParams}} } try { - String response = apiInvoker.invokeAPI(basePath, path, "{{httpMethod}}", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "{{httpMethod}}", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ - return {{#returnType}}({{{returnType}}}) ApiInvoker.deserialize(response, "{{returnContainer}}", {{returnBaseType}}.class){{/returnType}}; + return {{#returnType}}({{{returnType}}}) apiClient.deserialize(response, "{{returnContainer}}", {{returnBaseType}}.class){{/returnType}}; } else { return {{#returnType}}null{{/returnType}}; From 62c8f9e1e2ebd4333cc21f6a881f6584bcdb3fc2 Mon Sep 17 00:00:00 2001 From: xhh Date: Tue, 26 May 2015 16:13:19 +0800 Subject: [PATCH 39/72] Rebuild Java Petstore sample --- .../{ApiInvoker.java => ApiClient.java} | 106 +++++++++--------- .../java/io/swagger/client/Configuration.java | 13 +++ .../java/io/swagger/client/api/PetApi.java | 70 ++++++------ .../java/io/swagger/client/api/StoreApi.java | 40 ++++--- .../java/io/swagger/client/api/UserApi.java | 52 +++++---- .../io/swagger/client/model/ApiResponse.java | 64 ----------- 6 files changed, 156 insertions(+), 189 deletions(-) rename samples/client/petstore/java/src/main/java/io/swagger/client/{ApiInvoker.java => ApiClient.java} (77%) create mode 100644 samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java delete mode 100644 samples/client/petstore/java/src/main/java/io/swagger/client/model/ApiResponse.java diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiInvoker.java b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java similarity index 77% rename from samples/client/petstore/java/src/main/java/io/swagger/client/ApiInvoker.java rename to samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java index 69d13136274..b937edfedd3 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiInvoker.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java @@ -29,65 +29,82 @@ import java.net.URLEncoder; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.text.DateFormat; import java.text.SimpleDateFormat; import java.text.ParseException; -public class ApiInvoker { - private static ApiInvoker INSTANCE = new ApiInvoker(); +public class ApiClient { private Map hostMap = new HashMap(); private Map defaultHeaderMap = new HashMap(); private boolean isDebug = false; + private String basePath = "http://petstore.swagger.io/v2"; - /** - * ISO 8601 date time format. - * @see https://en.wikipedia.org/wiki/ISO_8601 - */ - public static final SimpleDateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + private DateFormat dateFormat; + private DateFormat datetimeFormat; - /** - * ISO 8601 date format. - * @see https://en.wikipedia.org/wiki/ISO_8601 - */ - public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); + public ApiClient() { + // Use ISO 8601 format for date and datetime. + // See https://en.wikipedia.org/wiki/ISO_8601 + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + this.datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - static { // Use UTC as the default time zone. - DATE_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); - DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + this.datetimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); // Set default User-Agent. setUserAgent("Java-Swagger"); } - public static void setUserAgent(String userAgent) { - INSTANCE.addDefaultHeader("User-Agent", userAgent); + public String getBasePath() { + return basePath; } - public static Date parseDateTime(String str) { + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + public ApiClient enableDebug() { + isDebug = true; + return this; + } + + public Date parseDateTime(String str) { try { - return DATE_TIME_FORMAT.parse(str); + return datetimeFormat.parse(str); } catch (java.text.ParseException e) { throw new RuntimeException(e); } } - public static Date parseDate(String str) { + public Date parseDate(String str) { try { - return DATE_FORMAT.parse(str); + return dateFormat.parse(str); } catch (java.text.ParseException e) { throw new RuntimeException(e); } } - public static String formatDateTime(Date datetime) { - return DATE_TIME_FORMAT.format(datetime); + public String formatDateTime(Date datetime) { + return datetimeFormat.format(datetime); } - public static String formatDate(Date date) { - return DATE_FORMAT.format(date); + public String formatDate(Date date) { + return dateFormat.format(date); } - public static String parameterToString(Object param) { + public String parameterToString(Object param) { if (param == null) { return ""; } else if (param instanceof Date) { @@ -105,17 +122,6 @@ public class ApiInvoker { return String.valueOf(param); } } - public void enableDebug() { - isDebug = true; - } - - public static ApiInvoker getInstance() { - return INSTANCE; - } - - public void addDefaultHeader(String key, String value) { - defaultHeaderMap.put(key, value); - } public String escapeString(String str) { try{ @@ -126,7 +132,7 @@ public class ApiInvoker { } } - public static Object deserialize(String json, String containerType, Class cls) throws ApiException { + public Object deserialize(String json, String containerType, Class cls) throws ApiException { if(null != containerType) { containerType = containerType.toLowerCase(); } @@ -151,7 +157,7 @@ public class ApiInvoker { } } - public static String serialize(Object obj) throws ApiException { + public String serialize(Object obj) throws ApiException { try { if (obj != null) return JsonUtil.getJsonMapper().writeValueAsString(obj); @@ -163,8 +169,8 @@ public class ApiInvoker { } } - public String invokeAPI(String host, String path, String method, Map queryParams, Object body, Map headerParams, Map formParams, String contentType) throws ApiException { - Client client = getClient(host); + public String invokeAPI(String path, String method, Map queryParams, Object body, Map headerParams, Map formParams, String contentType) throws ApiException { + Client client = getClient(); StringBuilder b = new StringBuilder(); @@ -180,7 +186,7 @@ public class ApiInvoker { } String querystring = b.toString(); - Builder builder = client.resource(host + path + querystring).accept("application/json"); + Builder builder = client.resource(basePath + path + querystring).accept("application/json"); for(String key : headerParams.keySet()) { builder = builder.header(key, headerParams.get(key)); } @@ -236,6 +242,7 @@ public class ApiInvoker { else { throw new ApiException(500, "unknown method type " + method); } + if(response.getClientResponseStatus() == ClientResponse.Status.NO_CONTENT) { return null; } @@ -267,8 +274,8 @@ public class ApiInvoker { StringBuilder formParamBuilder = new StringBuilder(); for (Entry param : formParams.entrySet()) { - String keyStr = ApiInvoker.parameterToString(param.getKey()); - String valueStr = ApiInvoker.parameterToString(param.getValue()); + String keyStr = parameterToString(param.getKey()); + String valueStr = parameterToString(param.getValue()); try { formParamBuilder.append(URLEncoder.encode(keyStr, "utf8")) @@ -287,14 +294,13 @@ public class ApiInvoker { return encodedFormParams; } - - private Client getClient(String host) { - if(!hostMap.containsKey(host)) { + private Client getClient() { + if(!hostMap.containsKey(basePath)) { Client client = Client.create(); if(isDebug) client.addFilter(new LoggingFilter()); - hostMap.put(host, client); + hostMap.put(basePath, client); } - return hostMap.get(host); + return hostMap.get(basePath); } -} \ No newline at end of file +} diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java b/samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java new file mode 100644 index 00000000000..63622ead5dc --- /dev/null +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java @@ -0,0 +1,13 @@ +package io.swagger.client; + +public class Configuration { + private static ApiClient defaultApiClient = new ApiClient(); + + public static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + public static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java b/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java index 10326d8a2d6..4d3d5c51d87 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java @@ -1,7 +1,8 @@ package io.swagger.client.api; import io.swagger.client.ApiException; -import io.swagger.client.ApiInvoker; +import io.swagger.client.ApiClient; +import io.swagger.client.Configuration; import io.swagger.client.model.*; @@ -20,19 +21,22 @@ import java.util.Map; import java.util.HashMap; public class PetApi { - String basePath = "http://petstore.swagger.io/v2"; - ApiInvoker apiInvoker = ApiInvoker.getInstance(); + private ApiClient apiClient; - public ApiInvoker getInvoker() { - return apiInvoker; + public PetApi() { + this(Configuration.getDefaultApiClient()); } - public void setBasePath(String basePath) { - this.basePath = basePath; + public PetApi(ApiClient apiClient) { + this.apiClient = apiClient; } - public String getBasePath() { - return basePath; + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; } @@ -74,7 +78,7 @@ public class PetApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "PUT", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "PUT", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } @@ -124,7 +128,7 @@ public class PetApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "POST", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } @@ -155,7 +159,7 @@ public class PetApi { Map formParams = new HashMap(); if (status != null) - queryParams.put("status", ApiInvoker.parameterToString(status)); + queryParams.put("status", apiClient.parameterToString(status)); String[] contentTypes = { @@ -176,9 +180,9 @@ public class PetApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "GET", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ - return (List) ApiInvoker.deserialize(response, "array", Pet.class); + return (List) apiClient.deserialize(response, "array", Pet.class); } else { return null; @@ -207,7 +211,7 @@ public class PetApi { Map formParams = new HashMap(); if (tags != null) - queryParams.put("tags", ApiInvoker.parameterToString(tags)); + queryParams.put("tags", apiClient.parameterToString(tags)); String[] contentTypes = { @@ -228,9 +232,9 @@ public class PetApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "GET", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ - return (List) ApiInvoker.deserialize(response, "array", Pet.class); + return (List) apiClient.deserialize(response, "array", Pet.class); } else { return null; @@ -257,7 +261,7 @@ public class PetApi { // create path and map variables String path = "/pet/{petId}".replaceAll("\\{format\\}","json") - .replaceAll("\\{" + "petId" + "\\}", apiInvoker.escapeString(petId.toString())); + .replaceAll("\\{" + "petId" + "\\}", apiClient.escapeString(petId.toString())); // query params Map queryParams = new HashMap(); @@ -284,9 +288,9 @@ public class PetApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "GET", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ - return (Pet) ApiInvoker.deserialize(response, "", Pet.class); + return (Pet) apiClient.deserialize(response, "", Pet.class); } else { return null; @@ -315,7 +319,7 @@ public class PetApi { // create path and map variables String path = "/pet/{petId}".replaceAll("\\{format\\}","json") - .replaceAll("\\{" + "petId" + "\\}", apiInvoker.escapeString(petId.toString())); + .replaceAll("\\{" + "petId" + "\\}", apiClient.escapeString(petId.toString())); // query params Map queryParams = new HashMap(); @@ -335,22 +339,22 @@ public class PetApi { FormDataMultiPart mp = new FormDataMultiPart(); hasFields = true; - mp.field("name", ApiInvoker.parameterToString(name), MediaType.MULTIPART_FORM_DATA_TYPE); + mp.field("name", apiClient.parameterToString(name), MediaType.MULTIPART_FORM_DATA_TYPE); hasFields = true; - mp.field("status", ApiInvoker.parameterToString(status), MediaType.MULTIPART_FORM_DATA_TYPE); + mp.field("status", apiClient.parameterToString(status), MediaType.MULTIPART_FORM_DATA_TYPE); if(hasFields) postBody = mp; } else { - formParams.put("name", ApiInvoker.parameterToString(name)); - formParams.put("status", ApiInvoker.parameterToString(status)); + formParams.put("name", apiClient.parameterToString(name)); + formParams.put("status", apiClient.parameterToString(status)); } try { - String response = apiInvoker.invokeAPI(basePath, path, "POST", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } @@ -380,7 +384,7 @@ public class PetApi { // create path and map variables String path = "/pet/{petId}".replaceAll("\\{format\\}","json") - .replaceAll("\\{" + "petId" + "\\}", apiInvoker.escapeString(petId.toString())); + .replaceAll("\\{" + "petId" + "\\}", apiClient.escapeString(petId.toString())); // query params Map queryParams = new HashMap(); @@ -388,7 +392,7 @@ public class PetApi { Map formParams = new HashMap(); - headerParams.put("api_key", ApiInvoker.parameterToString(apiKey)); + headerParams.put("api_key", apiClient.parameterToString(apiKey)); String[] contentTypes = { @@ -408,7 +412,7 @@ public class PetApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "DELETE", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "DELETE", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } @@ -439,7 +443,7 @@ public class PetApi { // create path and map variables String path = "/pet/{petId}/uploadImage".replaceAll("\\{format\\}","json") - .replaceAll("\\{" + "petId" + "\\}", apiInvoker.escapeString(petId.toString())); + .replaceAll("\\{" + "petId" + "\\}", apiClient.escapeString(petId.toString())); // query params Map queryParams = new HashMap(); @@ -459,7 +463,7 @@ public class PetApi { FormDataMultiPart mp = new FormDataMultiPart(); hasFields = true; - mp.field("additionalMetadata", ApiInvoker.parameterToString(additionalMetadata), MediaType.MULTIPART_FORM_DATA_TYPE); + mp.field("additionalMetadata", apiClient.parameterToString(additionalMetadata), MediaType.MULTIPART_FORM_DATA_TYPE); hasFields = true; mp.field("file", file.getName()); @@ -469,13 +473,13 @@ public class PetApi { postBody = mp; } else { - formParams.put("additionalMetadata", ApiInvoker.parameterToString(additionalMetadata)); + formParams.put("additionalMetadata", apiClient.parameterToString(additionalMetadata)); } try { - String response = apiInvoker.invokeAPI(basePath, path, "POST", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/api/StoreApi.java b/samples/client/petstore/java/src/main/java/io/swagger/client/api/StoreApi.java index 6da7b5abb2f..7b956f79a22 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/api/StoreApi.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/api/StoreApi.java @@ -1,7 +1,8 @@ package io.swagger.client.api; import io.swagger.client.ApiException; -import io.swagger.client.ApiInvoker; +import io.swagger.client.ApiClient; +import io.swagger.client.Configuration; import io.swagger.client.model.*; @@ -20,19 +21,22 @@ import java.util.Map; import java.util.HashMap; public class StoreApi { - String basePath = "http://petstore.swagger.io/v2"; - ApiInvoker apiInvoker = ApiInvoker.getInstance(); + private ApiClient apiClient; - public ApiInvoker getInvoker() { - return apiInvoker; + public StoreApi() { + this(Configuration.getDefaultApiClient()); } - public void setBasePath(String basePath) { - this.basePath = basePath; + public StoreApi(ApiClient apiClient) { + this.apiClient = apiClient; } - public String getBasePath() { - return basePath; + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; } @@ -73,9 +77,9 @@ public class StoreApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "GET", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ - return (Map) ApiInvoker.deserialize(response, "map", Map.class); + return (Map) apiClient.deserialize(response, "map", Map.class); } else { return null; @@ -123,9 +127,9 @@ public class StoreApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "POST", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ - return (Order) ApiInvoker.deserialize(response, "", Order.class); + return (Order) apiClient.deserialize(response, "", Order.class); } else { return null; @@ -152,7 +156,7 @@ public class StoreApi { // create path and map variables String path = "/store/order/{orderId}".replaceAll("\\{format\\}","json") - .replaceAll("\\{" + "orderId" + "\\}", apiInvoker.escapeString(orderId.toString())); + .replaceAll("\\{" + "orderId" + "\\}", apiClient.escapeString(orderId.toString())); // query params Map queryParams = new HashMap(); @@ -179,9 +183,9 @@ public class StoreApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "GET", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ - return (Order) ApiInvoker.deserialize(response, "", Order.class); + return (Order) apiClient.deserialize(response, "", Order.class); } else { return null; @@ -208,7 +212,7 @@ public class StoreApi { // create path and map variables String path = "/store/order/{orderId}".replaceAll("\\{format\\}","json") - .replaceAll("\\{" + "orderId" + "\\}", apiInvoker.escapeString(orderId.toString())); + .replaceAll("\\{" + "orderId" + "\\}", apiClient.escapeString(orderId.toString())); // query params Map queryParams = new HashMap(); @@ -235,7 +239,7 @@ public class StoreApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "DELETE", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "DELETE", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/api/UserApi.java b/samples/client/petstore/java/src/main/java/io/swagger/client/api/UserApi.java index d0974d95a52..0c6f331abe0 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/api/UserApi.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/api/UserApi.java @@ -1,7 +1,8 @@ package io.swagger.client.api; import io.swagger.client.ApiException; -import io.swagger.client.ApiInvoker; +import io.swagger.client.ApiClient; +import io.swagger.client.Configuration; import io.swagger.client.model.*; @@ -20,19 +21,22 @@ import java.util.Map; import java.util.HashMap; public class UserApi { - String basePath = "http://petstore.swagger.io/v2"; - ApiInvoker apiInvoker = ApiInvoker.getInstance(); + private ApiClient apiClient; - public ApiInvoker getInvoker() { - return apiInvoker; + public UserApi() { + this(Configuration.getDefaultApiClient()); } - public void setBasePath(String basePath) { - this.basePath = basePath; + public UserApi(ApiClient apiClient) { + this.apiClient = apiClient; } - public String getBasePath() { - return basePath; + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; } @@ -74,7 +78,7 @@ public class UserApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "POST", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } @@ -124,7 +128,7 @@ public class UserApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "POST", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } @@ -174,7 +178,7 @@ public class UserApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "POST", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } @@ -206,9 +210,9 @@ public class UserApi { Map formParams = new HashMap(); if (username != null) - queryParams.put("username", ApiInvoker.parameterToString(username)); + queryParams.put("username", apiClient.parameterToString(username)); if (password != null) - queryParams.put("password", ApiInvoker.parameterToString(password)); + queryParams.put("password", apiClient.parameterToString(password)); String[] contentTypes = { @@ -229,9 +233,9 @@ public class UserApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "GET", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ - return (String) ApiInvoker.deserialize(response, "", String.class); + return (String) apiClient.deserialize(response, "", String.class); } else { return null; @@ -278,7 +282,7 @@ public class UserApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "GET", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } @@ -307,7 +311,7 @@ public class UserApi { // create path and map variables String path = "/user/{username}".replaceAll("\\{format\\}","json") - .replaceAll("\\{" + "username" + "\\}", apiInvoker.escapeString(username.toString())); + .replaceAll("\\{" + "username" + "\\}", apiClient.escapeString(username.toString())); // query params Map queryParams = new HashMap(); @@ -334,9 +338,9 @@ public class UserApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "GET", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ - return (User) ApiInvoker.deserialize(response, "", User.class); + return (User) apiClient.deserialize(response, "", User.class); } else { return null; @@ -364,7 +368,7 @@ public class UserApi { // create path and map variables String path = "/user/{username}".replaceAll("\\{format\\}","json") - .replaceAll("\\{" + "username" + "\\}", apiInvoker.escapeString(username.toString())); + .replaceAll("\\{" + "username" + "\\}", apiClient.escapeString(username.toString())); // query params Map queryParams = new HashMap(); @@ -391,7 +395,7 @@ public class UserApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "PUT", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "PUT", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } @@ -420,7 +424,7 @@ public class UserApi { // create path and map variables String path = "/user/{username}".replaceAll("\\{format\\}","json") - .replaceAll("\\{" + "username" + "\\}", apiInvoker.escapeString(username.toString())); + .replaceAll("\\{" + "username" + "\\}", apiClient.escapeString(username.toString())); // query params Map queryParams = new HashMap(); @@ -447,7 +451,7 @@ public class UserApi { } try { - String response = apiInvoker.invokeAPI(basePath, path, "DELETE", queryParams, postBody, headerParams, formParams, contentType); + String response = apiClient.invokeAPI(path, "DELETE", queryParams, postBody, headerParams, formParams, contentType); if(response != null){ return ; } diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/model/ApiResponse.java b/samples/client/petstore/java/src/main/java/io/swagger/client/model/ApiResponse.java deleted file mode 100644 index cd9ff24975c..00000000000 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/model/ApiResponse.java +++ /dev/null @@ -1,64 +0,0 @@ -package io.swagger.client.model; - - -import com.wordnik.swagger.annotations.*; -import com.fasterxml.jackson.annotation.JsonProperty; - - -@ApiModel(description = "") -public class ApiResponse { - - private Integer code = null; - private String type = null; - private String message = null; - - - /** - **/ - @ApiModelProperty(required = false, value = "") - @JsonProperty("code") - public Integer getCode() { - return code; - } - public void setCode(Integer code) { - this.code = code; - } - - - /** - **/ - @ApiModelProperty(required = false, value = "") - @JsonProperty("type") - public String getType() { - return type; - } - public void setType(String type) { - this.type = type; - } - - - /** - **/ - @ApiModelProperty(required = false, value = "") - @JsonProperty("message") - public String getMessage() { - return message; - } - public void setMessage(String message) { - this.message = message; - } - - - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class ApiResponse {\n"); - - sb.append(" code: ").append(code).append("\n"); - sb.append(" type: ").append(type).append("\n"); - sb.append(" message: ").append(message).append("\n"); - sb.append("}\n"); - return sb.toString(); - } -} From a8c526efd5588ed6cac259f94b2421262882eb97 Mon Sep 17 00:00:00 2001 From: xhh Date: Tue, 26 May 2015 16:41:04 +0800 Subject: [PATCH 40/72] Add unit tests for Configuration and ApiClient --- .../main/resources/Java/ApiClient.mustache | 4 +++ .../java/io/swagger/client/ApiClient.java | 4 +++ .../io/swagger/client/ConfigurationTest.java | 14 +++++++++ .../io/swagger/petstore/test/PetApiTest.java | 29 +++++++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 samples/client/petstore/java/src/test/java/io/swagger/client/ConfigurationTest.java diff --git a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache index cd0805d775f..239ce54a34a 100644 --- a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache @@ -75,6 +75,10 @@ public class ApiClient { return this; } + public boolean isDebug() { + return isDebug; + } + public ApiClient enableDebug() { isDebug = true; return this; diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java index b937edfedd3..ec0a150ef4e 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java @@ -75,6 +75,10 @@ public class ApiClient { return this; } + public boolean isDebug() { + return isDebug; + } + public ApiClient enableDebug() { isDebug = true; return this; diff --git a/samples/client/petstore/java/src/test/java/io/swagger/client/ConfigurationTest.java b/samples/client/petstore/java/src/test/java/io/swagger/client/ConfigurationTest.java new file mode 100644 index 00000000000..e16eaf4c086 --- /dev/null +++ b/samples/client/petstore/java/src/test/java/io/swagger/client/ConfigurationTest.java @@ -0,0 +1,14 @@ +package io.swagger.client; + +import static org.junit.Assert.*; +import org.junit.*; + +public class ConfigurationTest { + @Test + public void testDefaultApiClient() { + ApiClient apiClient = Configuration.getDefaultApiClient(); + assertNotNull(apiClient); + assertEquals("http://petstore.swagger.io/v2", apiClient.getBasePath()); + assertFalse(apiClient.isDebug()); + } +} diff --git a/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java b/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java index 1bee31e0748..8416e13b468 100644 --- a/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java +++ b/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java @@ -1,6 +1,8 @@ package io.swagger.petstore.test; import io.swagger.client.ApiException; +import io.swagger.client.ApiClient; +import io.swagger.client.Configuration; import io.swagger.client.api.*; import io.swagger.client.model.*; @@ -18,6 +20,33 @@ public class PetApiTest { api = new PetApi(); } + @Test + public void testApiClient() { + // the default api client is used + assertEquals(Configuration.getDefaultApiClient(), api.getApiClient()); + assertNotNull(api.getApiClient()); + assertEquals("http://petstore.swagger.io/v2", api.getApiClient().getBasePath()); + assertFalse(api.getApiClient().isDebug()); + + ApiClient oldClient = api.getApiClient(); + + ApiClient newClient = new ApiClient(); + newClient.setBasePath("http://example.com"); + newClient.enableDebug(); + + // set api client via constructor + api = new PetApi(newClient); + assertNotNull(api.getApiClient()); + assertEquals("http://example.com", api.getApiClient().getBasePath()); + assertTrue(api.getApiClient().isDebug()); + + // set api client via setter method + api.setApiClient(oldClient); + assertNotNull(api.getApiClient()); + assertEquals("http://petstore.swagger.io/v2", api.getApiClient().getBasePath()); + assertFalse(api.getApiClient().isDebug()); + } + @Test public void testCreateAndGetPet() throws Exception { Pet pet = createRandomPet(); From 18cf6bcfa64e380f8a39d2d02a4970152f3aa08a Mon Sep 17 00:00:00 2001 From: geekerzp Date: Fri, 29 May 2015 15:09:19 +0800 Subject: [PATCH 41/72] Updated python client. Verified HTTPS with SSL/TLS. --- .../src/main/resources/python/rest.mustache | 51 +++++++++++++------ .../src/main/resources/python/setup.mustache | 2 +- .../SwaggerPetstore/rest.py | 51 +++++++++++++------ .../python/SwaggerPetstore-python/setup.py | 2 +- 4 files changed, 74 insertions(+), 32 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/python/rest.mustache b/modules/swagger-codegen/src/main/resources/python/rest.mustache index 06b817da757..da99abc2493 100644 --- a/modules/swagger-codegen/src/main/resources/python/rest.mustache +++ b/modules/swagger-codegen/src/main/resources/python/rest.mustache @@ -2,6 +2,8 @@ import sys import io import json +import ssl +import certifi # python 2 and python 3 compatibility library from six import iteritems @@ -42,10 +44,30 @@ class RESTResponse(io.IOBase): class RESTClientObject(object): def __init__(self, pools_size=4): + # http pool manager self.pool_manager = urllib3.PoolManager( num_pools=pools_size ) + # https pool manager + # certificates validated using Mozilla’s root certificates + self.ssl_pool_manager = urllib3.PoolManager( + num_pools=pools_size, + cert_reqs=ssl.CERT_REQUIRED, + ca_certs=certifi.where() + ) + + def agent(self, url): + """ + Return proper pool manager for the http\https schemes. + """ + url = urllib3.util.url.parse_url(url) + scheme = url.scheme + if scheme == 'https': + return self.ssl_pool_manager + else: + return self.pool_manager + def request(self, method, url, query_params=None, headers=None, body=None, post_params=None): """ @@ -56,7 +78,6 @@ class RESTClientObject(object): :param body: request json body, for `application/json` :param post_params: request post parameters, `application/x-www-form-urlencode` and `multipart/form-data` - :param raw_response: if return the raw response """ method = method.upper() assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', 'PATCH'] @@ -75,27 +96,27 @@ class RESTClientObject(object): if query_params: url += '?' + urlencode(query_params) if headers['Content-Type'] == 'application/json': - r = self.pool_manager.request(method, url, - body=json.dumps(body), - headers=headers) + r = self.agent(url).request(method, url, + body=json.dumps(body), + headers=headers) if headers['Content-Type'] == 'application/x-www-form-urlencoded': - r = self.pool_manager.request(method, url, - fields=post_params, - encode_multipart=False, - headers=headers) + r = self.agent(url).request(method, url, + fields=post_params, + encode_multipart=False, + headers=headers) if headers['Content-Type'] == 'multipart/form-data': # must del headers['Content-Type'], or the correct Content-Type # which generated by urllib3 will be overwritten. del headers['Content-Type'] - r = self.pool_manager.request(method, url, - fields=post_params, - encode_multipart=True, - headers=headers) + r = self.agent(url).request(method, url, + fields=post_params, + encode_multipart=True, + headers=headers) # For `GET`, `HEAD`, `DELETE` else: - r = self.pool_manager.request(method, url, - fields=query_params, - headers=headers) + r = self.agent(url).request(method, url, + fields=query_params, + headers=headers) r = RESTResponse(r) if r.status not in range(200, 206): diff --git a/modules/swagger-codegen/src/main/resources/python/setup.mustache b/modules/swagger-codegen/src/main/resources/python/setup.mustache index a049057c920..f1ba52d2930 100644 --- a/modules/swagger-codegen/src/main/resources/python/setup.mustache +++ b/modules/swagger-codegen/src/main/resources/python/setup.mustache @@ -12,7 +12,7 @@ from setuptools import setup, find_packages # Try reading the setuptools documentation: # http://pypi.python.org/pypi/setuptools -REQUIRES = ["urllib3 >= 1.10", "six >= 1.9"] +REQUIRES = ["urllib3 >= 1.10", "six >= 1.9", "certifi"] setup( name="{{module}}", diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/rest.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/rest.py index 06b817da757..da99abc2493 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/rest.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/rest.py @@ -2,6 +2,8 @@ import sys import io import json +import ssl +import certifi # python 2 and python 3 compatibility library from six import iteritems @@ -42,10 +44,30 @@ class RESTResponse(io.IOBase): class RESTClientObject(object): def __init__(self, pools_size=4): + # http pool manager self.pool_manager = urllib3.PoolManager( num_pools=pools_size ) + # https pool manager + # certificates validated using Mozilla’s root certificates + self.ssl_pool_manager = urllib3.PoolManager( + num_pools=pools_size, + cert_reqs=ssl.CERT_REQUIRED, + ca_certs=certifi.where() + ) + + def agent(self, url): + """ + Return proper pool manager for the http\https schemes. + """ + url = urllib3.util.url.parse_url(url) + scheme = url.scheme + if scheme == 'https': + return self.ssl_pool_manager + else: + return self.pool_manager + def request(self, method, url, query_params=None, headers=None, body=None, post_params=None): """ @@ -56,7 +78,6 @@ class RESTClientObject(object): :param body: request json body, for `application/json` :param post_params: request post parameters, `application/x-www-form-urlencode` and `multipart/form-data` - :param raw_response: if return the raw response """ method = method.upper() assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', 'PATCH'] @@ -75,27 +96,27 @@ class RESTClientObject(object): if query_params: url += '?' + urlencode(query_params) if headers['Content-Type'] == 'application/json': - r = self.pool_manager.request(method, url, - body=json.dumps(body), - headers=headers) + r = self.agent(url).request(method, url, + body=json.dumps(body), + headers=headers) if headers['Content-Type'] == 'application/x-www-form-urlencoded': - r = self.pool_manager.request(method, url, - fields=post_params, - encode_multipart=False, - headers=headers) + r = self.agent(url).request(method, url, + fields=post_params, + encode_multipart=False, + headers=headers) if headers['Content-Type'] == 'multipart/form-data': # must del headers['Content-Type'], or the correct Content-Type # which generated by urllib3 will be overwritten. del headers['Content-Type'] - r = self.pool_manager.request(method, url, - fields=post_params, - encode_multipart=True, - headers=headers) + r = self.agent(url).request(method, url, + fields=post_params, + encode_multipart=True, + headers=headers) # For `GET`, `HEAD`, `DELETE` else: - r = self.pool_manager.request(method, url, - fields=query_params, - headers=headers) + r = self.agent(url).request(method, url, + fields=query_params, + headers=headers) r = RESTResponse(r) if r.status not in range(200, 206): diff --git a/samples/client/petstore/python/SwaggerPetstore-python/setup.py b/samples/client/petstore/python/SwaggerPetstore-python/setup.py index fd0b786efa3..50a6ffeb00c 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/setup.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/setup.py @@ -12,7 +12,7 @@ from setuptools import setup, find_packages # Try reading the setuptools documentation: # http://pypi.python.org/pypi/setuptools -REQUIRES = ["urllib3 >= 1.10", "six >= 1.9"] +REQUIRES = ["urllib3 >= 1.10", "six >= 1.9", "certifi"] setup( name="SwaggerPetstore", From 5f36ad3b75846272db1e20e26a461e4e9f22bc8b Mon Sep 17 00:00:00 2001 From: wing328 Date: Fri, 29 May 2015 16:43:27 +0800 Subject: [PATCH 42/72] add authentication support --- .../main/resources/csharp/ApiClient.mustache | 81 +++++++++++++++-- .../resources/csharp/Configuration.mustache | 33 +++++++ .../src/main/resources/csharp/api.mustache | 52 ++++++----- .../resources/csharp/apiException.mustache | 18 +++- .../src/main/resources/csharp/model.mustache | 21 ++++- .../src/main/csharp/io/swagger/Api/PetApi.cs | 87 +++++++++++++------ .../main/csharp/io/swagger/Api/StoreApi.cs | 67 +++++++++----- .../src/main/csharp/io/swagger/Api/UserApi.cs | 87 +++++++++++++------ .../main/csharp/io/swagger/Model/Category.cs | 21 ++++- .../src/main/csharp/io/swagger/Model/Order.cs | 21 ++++- .../src/main/csharp/io/swagger/Model/Pet.cs | 21 ++++- .../src/main/csharp/io/swagger/Model/Tag.cs | 21 ++++- .../src/main/csharp/io/swagger/Model/User.cs | 21 ++++- .../csharp/io/swagger/client/ApiClient.cs | 86 ++++++++++++++++-- .../csharp/io/swagger/client/ApiException.cs | 18 +++- .../csharp/io/swagger/client/Configuration.cs | 33 +++++++ 16 files changed, 569 insertions(+), 119 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache index 469d5e94c37..c841efdc1b5 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache @@ -8,26 +8,41 @@ using Newtonsoft.Json; using RestSharp; namespace {{invokerPackage}} { + /// + /// API client is mainly responible for making the HTTP call to the API backend + /// public class ApiClient { - public ApiClient() { - this.basePath = "{{basePath}}"; - this.restClient = new RestClient(this.basePath); - } - public ApiClient(String basePath) { + /// + /// Initializes a new instance of the class. + /// + /// The base path. + public ApiClient(String basePath="{{basePath}}") { this.basePath = basePath; this.restClient = new RestClient(this.basePath); } + /// + /// Gets or sets the base path. + /// + /// The base path. public string basePath { get; set; } + + /// + /// Gets or sets the RestClient + /// + /// The RestClient. public RestClient restClient { get; set; } + private Dictionary defaultHeaderMap = new Dictionary(); public Object CallApi(String Path, RestSharp.Method Method, Dictionary QueryParams, String PostBody, - Dictionary HeaderParams, Dictionary FormParams, Dictionary FileParams) { + Dictionary HeaderParams, Dictionary FormParams, Dictionary FileParams, String[] AuthSettings) { var request = new RestRequest(Path, Method); + UpdateParamsForAuth(QueryParams, HeaderParams, AuthSettings); + // add default header, if any foreach(KeyValuePair defaultHeader in this.defaultHeaderMap) request.AddHeader(defaultHeader.Key, defaultHeader.Value); @@ -126,5 +141,59 @@ namespace {{invokerPackage}} { throw new ApiException(500, e.Message); } } + + /// + /// Get the API key with prefix + /// + /// Object + /// API key with prefix + public string GetApiKeyWithPrefix (string apiKey) + { + var apiKeyValue = ""; + Configuration.apiKey.TryGetValue (apiKey, out apiKeyValue); + var apiKeyPrefix = ""; + if (Configuration.apiKeyPrefix.TryGetValue (apiKey, out apiKeyPrefix)) { + return apiKeyPrefix + " " + apiKeyValue; + } else { + return apiKeyValue; + } + } + + /// + /// Update parameters based on authentication + /// + /// Query parameters + /// Header parameters + /// Authentication settings + public void UpdateParamsForAuth(Dictionary QueryParams, Dictionary HeaderParams, string[] AuthSettings) { + if (AuthSettings == null || AuthSettings.Length == 0) + return; + + foreach (string auth in AuthSettings) { + // determine which one to use + switch(auth) { + {{#authMethods}} + case "{{name}}": + {{#isApiKey}}{{#isKeyInHeader}}HeaderParams["{{keyParamName}}"] = GetApiKeyWithPrefix("{{keyParamName}}");{{/isKeyInHeader}}{{#isKeyInQuery}}QueryParams["{{keyParamName}}"] = GetApiKeyWithPrefix("{{keyParamName}}");{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}HeaderParams["Authorization"] = "Basic " + Base64Encode(Configuration.username + ":" + Configuration.password);{{/isBasic}} + {{#isOAuth}}//TODO support oauth{{/isOAuth}} + break; + {{/authMethods}} + default: + //TODO show warning about security definition not found + break; + } + } + + } + + /// + /// Encode string in base64 format + /// + /// String to be encoded + public static string Base64Encode(string text) { + var textByte = System.Text.Encoding.UTF8.GetBytes(text); + return System.Convert.ToBase64String(textByte); + } + } } diff --git a/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache b/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache index 41c371be487..1f5c00a356d 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache @@ -7,8 +7,41 @@ using System.Text; using {{invokerPackage}}; namespace {{invokerPackage}} { + /// + /// Represents a set of configuration settings + /// public class Configuration{ + + /// + /// Gets or sets the API client. This is the default API client for making HTTP calls. + /// + /// The API client. public static ApiClient apiClient = new ApiClient(); + /// + /// Gets or sets the username (HTTP basic authentication) + /// + /// The username. + public static String username { get; set; } + + /// + /// Gets or sets the password (HTTP basic authentication) + /// + /// The password. + public static String password { get; set; } + + /// + /// Gets or sets the API key based on the authentication name + /// + /// The API key. + public static Dictionary apiKey = new Dictionary(); + + /// + /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name + /// + /// The prefix of the API key. + public static Dictionary apiKeyPrefix = new Dictionary(); + + } } diff --git a/modules/swagger-codegen/src/main/resources/csharp/api.mustache b/modules/swagger-codegen/src/main/resources/csharp/api.mustache index c78b7461c7e..8e4a468add3 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/api.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/api.mustache @@ -8,20 +8,14 @@ using {{modelPackage}}; namespace {{package}} { {{#operations}} + /// + /// Represents a collection of functions to interact with the API endpoints + /// public class {{classname}} { - string basePath; - public ApiClient apiClient {get; set;} - - public {{classname}}(String basePath = "{{basePath}}") - { - this.basePath = basePath; - this.apiClient = new ApiClient(basePath); - } - /// - /// Create a new object + /// Initializes a new instance of the class. /// - /// an instance of ApiClient + /// an instance of ApiClient (optional) /// public {{classname}}(ApiClient apiClient = null) { if (apiClient == null) { // use the default one in Configuration @@ -32,22 +26,37 @@ namespace {{package}} { } /// - /// Sets the endpoint base url for the services being accessed + /// Initializes a new instance of the class. /// - /// Base URL /// - public void SetBasePath(string basePath) { - this.basePath = basePath; + public {{classname}}(String basePath) + { + this.apiClient = new ApiClient(basePath); } /// - /// Gets the endpoint base url for the services being accessed - /// Base URL + /// Sets the base path of the API client. /// - public String GetBasePath() { - return this.basePath; + /// The base path + public void SetBasePath(String basePath) { + this.apiClient.basePath = basePath; } + /// + /// Gets the base path of the API client. + /// + /// The base path + public String GetBasePath(String basePath) { + return this.apiClient.basePath; + } + + /// + /// Gets or sets the API client. + /// + /// The API client + public ApiClient apiClient {get; set;} + + {{#operation}} /// /// {{summary}} {{notes}} @@ -82,8 +91,11 @@ namespace {{package}} { {{#bodyParam}}postBody = apiClient.Serialize({{paramName}}); // http body (model) parameter {{/bodyParam}} + // authentication setting, if any + String[] authSettings = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content); diff --git a/modules/swagger-codegen/src/main/resources/csharp/apiException.mustache b/modules/swagger-codegen/src/main/resources/csharp/apiException.mustache index f28eb8de6f7..fd68a46a976 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/apiException.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/apiException.mustache @@ -1,13 +1,27 @@ using System; namespace {{invokerPackage}} { - + /// + /// API Exception + /// public class ApiException : Exception { - + /// + /// Gets or sets the error code (HTTP status code) + /// + /// The error code (HTTP status code). public int ErrorCode { get; set; } + /// + /// Initializes a new instance of the class. + /// + /// The base path. public ApiException() {} + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. public ApiException(int errorCode, string message) : base(message) { this.ErrorCode = errorCode; } diff --git a/modules/swagger-codegen/src/main/resources/csharp/model.mustache b/modules/swagger-codegen/src/main/resources/csharp/model.mustache index a8a3aa3a7a2..ce0e62de192 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/model.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/model.mustache @@ -3,10 +3,15 @@ using System.Text; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; +using Newtonsoft.Json; {{#models}} {{#model}} namespace {{package}} { + + /// + /// {{description}} + /// [DataContract] public class {{classname}} { {{#vars}} @@ -15,6 +20,11 @@ namespace {{package}} { public {{{datatype}}} {{name}} { get; set; } {{/vars}} + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object public override string ToString() { var sb = new StringBuilder(); sb.Append("class {{classname}} {\n"); @@ -24,7 +34,16 @@ namespace {{package}} { sb.Append("}\n"); return sb.ToString(); } - } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} {{/model}} {{/models}} } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs index 4c7cd680bed..1f7ddccfb26 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs @@ -6,20 +6,14 @@ using IO.Swagger.Model; namespace IO.Swagger.Api { + /// + /// Represents a collection of functions to interact with the API endpoints + /// public class PetApi { - string basePath; - public ApiClient apiClient {get; set;} - - public PetApi(String basePath = "http://petstore.swagger.io/v2") - { - this.basePath = basePath; - this.apiClient = new ApiClient(basePath); - } - /// - /// Create a new object + /// Initializes a new instance of the class. /// - /// an instance of ApiClient + /// an instance of ApiClient (optional) /// public PetApi(ApiClient apiClient = null) { if (apiClient == null) { // use the default one in Configuration @@ -30,22 +24,37 @@ namespace IO.Swagger.Api { } /// - /// Sets the endpoint base url for the services being accessed + /// Initializes a new instance of the class. /// - /// Base URL /// - public void SetBasePath(string basePath) { - this.basePath = basePath; + public PetApi(String basePath) + { + this.apiClient = new ApiClient(basePath); } /// - /// Gets the endpoint base url for the services being accessed - /// Base URL + /// Sets the base path of the API client. /// - public String GetBasePath() { - return this.basePath; + /// The base path + public void SetBasePath(String basePath) { + this.apiClient.basePath = basePath; } + /// + /// Gets the base path of the API client. + /// + /// The base path + public String GetBasePath(String basePath) { + return this.apiClient.basePath; + } + + /// + /// Gets or sets the API client. + /// + /// The API client + public ApiClient apiClient {get; set;} + + /// /// Update an existing pet @@ -72,8 +81,11 @@ namespace IO.Swagger.Api { postBody = apiClient.Serialize(Body); // http body (model) parameter + // authentication setting, if any + String[] authSettings = new String[] { "petstore_auth" }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.PUT, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.PUT, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UpdatePet: " + response.Content); @@ -107,8 +119,11 @@ namespace IO.Swagger.Api { postBody = apiClient.Serialize(Body); // http body (model) parameter + // authentication setting, if any + String[] authSettings = new String[] { "petstore_auth" }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling AddPet: " + response.Content); @@ -142,8 +157,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { "petstore_auth" }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling FindPetsByStatus: " + response.Content); @@ -176,8 +194,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { "petstore_auth" }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling FindPetsByTags: " + response.Content); @@ -213,8 +234,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { "api_key", "petstore_auth" }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetPetById: " + response.Content); @@ -254,8 +278,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { "petstore_auth" }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UpdatePetWithForm: " + response.Content); @@ -294,8 +321,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { "petstore_auth" }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling DeletePet: " + response.Content); @@ -336,8 +366,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { "petstore_auth" }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UploadFile: " + response.Content); diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs index 9fa4a528a07..a789b3502a0 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs @@ -6,20 +6,14 @@ using IO.Swagger.Model; namespace IO.Swagger.Api { + /// + /// Represents a collection of functions to interact with the API endpoints + /// public class StoreApi { - string basePath; - public ApiClient apiClient {get; set;} - - public StoreApi(String basePath = "http://petstore.swagger.io/v2") - { - this.basePath = basePath; - this.apiClient = new ApiClient(basePath); - } - /// - /// Create a new object + /// Initializes a new instance of the class. /// - /// an instance of ApiClient + /// an instance of ApiClient (optional) /// public StoreApi(ApiClient apiClient = null) { if (apiClient == null) { // use the default one in Configuration @@ -30,22 +24,37 @@ namespace IO.Swagger.Api { } /// - /// Sets the endpoint base url for the services being accessed + /// Initializes a new instance of the class. /// - /// Base URL /// - public void SetBasePath(string basePath) { - this.basePath = basePath; + public StoreApi(String basePath) + { + this.apiClient = new ApiClient(basePath); } /// - /// Gets the endpoint base url for the services being accessed - /// Base URL + /// Sets the base path of the API client. /// - public String GetBasePath() { - return this.basePath; + /// The base path + public void SetBasePath(String basePath) { + this.apiClient.basePath = basePath; } + /// + /// Gets the base path of the API client. + /// + /// The base path + public String GetBasePath(String basePath) { + return this.apiClient.basePath; + } + + /// + /// Gets or sets the API client. + /// + /// The API client + public ApiClient apiClient {get; set;} + + /// /// Returns pet inventories by status Returns a map of status codes to quantities @@ -70,8 +79,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { "api_key" }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetInventory: " + response.Content); @@ -104,8 +116,11 @@ namespace IO.Swagger.Api { postBody = apiClient.Serialize(Body); // http body (model) parameter + // authentication setting, if any + String[] authSettings = new String[] { }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling PlaceOrder: " + response.Content); @@ -141,8 +156,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetOrderById: " + response.Content); @@ -178,8 +196,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling DeleteOrder: " + response.Content); diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs index 0d6707d88cf..35de41c2257 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs @@ -6,20 +6,14 @@ using IO.Swagger.Model; namespace IO.Swagger.Api { + /// + /// Represents a collection of functions to interact with the API endpoints + /// public class UserApi { - string basePath; - public ApiClient apiClient {get; set;} - - public UserApi(String basePath = "http://petstore.swagger.io/v2") - { - this.basePath = basePath; - this.apiClient = new ApiClient(basePath); - } - /// - /// Create a new object + /// Initializes a new instance of the class. /// - /// an instance of ApiClient + /// an instance of ApiClient (optional) /// public UserApi(ApiClient apiClient = null) { if (apiClient == null) { // use the default one in Configuration @@ -30,22 +24,37 @@ namespace IO.Swagger.Api { } /// - /// Sets the endpoint base url for the services being accessed + /// Initializes a new instance of the class. /// - /// Base URL /// - public void SetBasePath(string basePath) { - this.basePath = basePath; + public UserApi(String basePath) + { + this.apiClient = new ApiClient(basePath); } /// - /// Gets the endpoint base url for the services being accessed - /// Base URL + /// Sets the base path of the API client. /// - public String GetBasePath() { - return this.basePath; + /// The base path + public void SetBasePath(String basePath) { + this.apiClient.basePath = basePath; } + /// + /// Gets the base path of the API client. + /// + /// The base path + public String GetBasePath(String basePath) { + return this.apiClient.basePath; + } + + /// + /// Gets or sets the API client. + /// + /// The API client + public ApiClient apiClient {get; set;} + + /// /// Create user This can only be done by the logged in user. @@ -72,8 +81,11 @@ namespace IO.Swagger.Api { postBody = apiClient.Serialize(Body); // http body (model) parameter + // authentication setting, if any + String[] authSettings = new String[] { }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling CreateUser: " + response.Content); @@ -107,8 +119,11 @@ namespace IO.Swagger.Api { postBody = apiClient.Serialize(Body); // http body (model) parameter + // authentication setting, if any + String[] authSettings = new String[] { }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling CreateUsersWithArrayInput: " + response.Content); @@ -142,8 +157,11 @@ namespace IO.Swagger.Api { postBody = apiClient.Serialize(Body); // http body (model) parameter + // authentication setting, if any + String[] authSettings = new String[] { }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.POST, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling CreateUsersWithListInput: " + response.Content); @@ -179,8 +197,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling LoginUser: " + response.Content); @@ -211,8 +232,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling LogoutUser: " + response.Content); @@ -249,8 +273,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling GetUserByName: " + response.Content); @@ -288,8 +315,11 @@ namespace IO.Swagger.Api { postBody = apiClient.Serialize(Body); // http body (model) parameter + // authentication setting, if any + String[] authSettings = new String[] { }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.PUT, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.PUT, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling UpdateUser: " + response.Content); @@ -326,8 +356,11 @@ namespace IO.Swagger.Api { + // authentication setting, if any + String[] authSettings = new String[] { }; + // make the HTTP request - IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams); + IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.DELETE, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling DeleteUser: " + response.Content); diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Category.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Category.cs index 04867ca365f..74121762af9 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Category.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Category.cs @@ -3,8 +3,13 @@ using System.Text; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; +using Newtonsoft.Json; namespace IO.Swagger.Model { + + /// + /// + /// [DataContract] public class Category { @@ -18,6 +23,11 @@ namespace IO.Swagger.Model { public string Name { get; set; } + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object public override string ToString() { var sb = new StringBuilder(); sb.Append("class Category {\n"); @@ -29,7 +39,16 @@ namespace IO.Swagger.Model { sb.Append("}\n"); return sb.ToString(); } - } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs index cf773a7a150..fd1643dbd29 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs @@ -3,8 +3,13 @@ using System.Text; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; +using Newtonsoft.Json; namespace IO.Swagger.Model { + + /// + /// + /// [DataContract] public class Order { @@ -38,6 +43,11 @@ namespace IO.Swagger.Model { public bool? Complete { get; set; } + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object public override string ToString() { var sb = new StringBuilder(); sb.Append("class Order {\n"); @@ -57,7 +67,16 @@ namespace IO.Swagger.Model { sb.Append("}\n"); return sb.ToString(); } - } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Pet.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Pet.cs index 41f4081d371..0bfba35b1e3 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Pet.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Pet.cs @@ -3,8 +3,13 @@ using System.Text; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; +using Newtonsoft.Json; namespace IO.Swagger.Model { + + /// + /// + /// [DataContract] public class Pet { @@ -38,6 +43,11 @@ namespace IO.Swagger.Model { public string Status { get; set; } + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object public override string ToString() { var sb = new StringBuilder(); sb.Append("class Pet {\n"); @@ -57,7 +67,16 @@ namespace IO.Swagger.Model { sb.Append("}\n"); return sb.ToString(); } - } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Tag.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Tag.cs index 44b6ae29297..53901491a47 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Tag.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Tag.cs @@ -3,8 +3,13 @@ using System.Text; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; +using Newtonsoft.Json; namespace IO.Swagger.Model { + + /// + /// + /// [DataContract] public class Tag { @@ -18,6 +23,11 @@ namespace IO.Swagger.Model { public string Name { get; set; } + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object public override string ToString() { var sb = new StringBuilder(); sb.Append("class Tag {\n"); @@ -29,7 +39,16 @@ namespace IO.Swagger.Model { sb.Append("}\n"); return sb.ToString(); } - } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/User.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/User.cs index 0fb3bfc86ce..e58d0296a06 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/User.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/User.cs @@ -3,8 +3,13 @@ using System.Text; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; +using Newtonsoft.Json; namespace IO.Swagger.Model { + + /// + /// + /// [DataContract] public class User { @@ -48,6 +53,11 @@ namespace IO.Swagger.Model { public int? UserStatus { get; set; } + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object public override string ToString() { var sb = new StringBuilder(); sb.Append("class User {\n"); @@ -71,7 +81,16 @@ namespace IO.Swagger.Model { sb.Append("}\n"); return sb.ToString(); } - } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs index 2a48e4b3075..c801bb1a736 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs @@ -8,26 +8,41 @@ using Newtonsoft.Json; using RestSharp; namespace IO.Swagger.Client { + /// + /// API client is mainly responible for making the HTTP call to the API backend + /// public class ApiClient { - public ApiClient() { - this.basePath = "http://petstore.swagger.io/v2"; - this.restClient = new RestClient(this.basePath); - } - public ApiClient(String basePath) { + /// + /// Initializes a new instance of the class. + /// + /// The base path. + public ApiClient(String basePath="http://petstore.swagger.io/v2") { this.basePath = basePath; this.restClient = new RestClient(this.basePath); } + /// + /// Gets or sets the base path. + /// + /// The base path. public string basePath { get; set; } + + /// + /// Gets or sets the RestClient + /// + /// The RestClient. public RestClient restClient { get; set; } + private Dictionary defaultHeaderMap = new Dictionary(); public Object CallApi(String Path, RestSharp.Method Method, Dictionary QueryParams, String PostBody, - Dictionary HeaderParams, Dictionary FormParams, Dictionary FileParams) { + Dictionary HeaderParams, Dictionary FormParams, Dictionary FileParams, String[] AuthSettings) { var request = new RestRequest(Path, Method); + UpdateParamsForAuth(QueryParams, HeaderParams, AuthSettings); + // add default header, if any foreach(KeyValuePair defaultHeader in this.defaultHeaderMap) request.AddHeader(defaultHeader.Key, defaultHeader.Value); @@ -126,5 +141,64 @@ namespace IO.Swagger.Client { throw new ApiException(500, e.Message); } } + + /// + /// Get the API key with prefix + /// + /// Object + /// API key with prefix + public string GetApiKeyWithPrefix (string apiKey) + { + var apiKeyValue = ""; + Configuration.apiKey.TryGetValue (apiKey, out apiKeyValue); + var apiKeyPrefix = ""; + if (Configuration.apiKeyPrefix.TryGetValue (apiKey, out apiKeyPrefix)) { + return apiKeyPrefix + " " + apiKeyValue; + } else { + return apiKeyValue; + } + } + + /// + /// Update parameters based on authentication + /// + /// Query parameters + /// Header parameters + /// Authentication settings + public void UpdateParamsForAuth(Dictionary QueryParams, Dictionary HeaderParams, string[] AuthSettings) { + if (AuthSettings == null || AuthSettings.Length == 0) + return; + + foreach (string auth in AuthSettings) { + // determine which one to use + switch(auth) { + + case "api_key": + HeaderParams["api_key"] = GetApiKeyWithPrefix("api_key"); + + break; + + case "petstore_auth": + + //TODO support oauth + break; + + default: + //TODO show warning about security definition not found + break; + } + } + + } + + /// + /// Encode string in base64 format + /// + /// String to be encoded + public static string Base64Encode(string text) { + var textByte = System.Text.Encoding.UTF8.GetBytes(text); + return System.Convert.ToBase64String(textByte); + } + } } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiException.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiException.cs index 7c4a7934681..691c2cd3fa2 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiException.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiException.cs @@ -1,13 +1,27 @@ using System; namespace IO.Swagger.Client { - + /// + /// API Exception + /// public class ApiException : Exception { - + /// + /// Gets or sets the error code (HTTP status code) + /// + /// The error code (HTTP status code). public int ErrorCode { get; set; } + /// + /// Initializes a new instance of the class. + /// + /// The base path. public ApiException() {} + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. public ApiException(int errorCode, string message) : base(message) { this.ErrorCode = errorCode; } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs index 815bb027c8f..4e7975e3ad0 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs @@ -7,8 +7,41 @@ using System.Text; using IO.Swagger.Client; namespace IO.Swagger.Client { + /// + /// Represents a set of configuration settings + /// public class Configuration{ + + /// + /// Gets or sets the API client. This is the default API client for making HTTP calls. + /// + /// The API client. public static ApiClient apiClient = new ApiClient(); + /// + /// Gets or sets the username (HTTP basic authentication) + /// + /// The username. + public static String username { get; set; } + + /// + /// Gets or sets the password (HTTP basic authentication) + /// + /// The password. + public static String password { get; set; } + + /// + /// Gets or sets the API key based on the authentication name + /// + /// The API key. + public static Dictionary apiKey = new Dictionary(); + + /// + /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name + /// + /// The prefix of the API key. + public static Dictionary apiKeyPrefix = new Dictionary(); + + } } From 34315f733822ac4a6cab16e703a90e323b990cd3 Mon Sep 17 00:00:00 2001 From: Ron Date: Fri, 29 May 2015 08:52:29 -0400 Subject: [PATCH 43/72] Create LICENSE --- LICENSE | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..542991f9550 --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +Copyright 2015 SmartBear Software + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at [apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. From 7d7ed15fdcb4d79bbf9c197ed6b8b43807ac1a5c Mon Sep 17 00:00:00 2001 From: Ron Date: Fri, 29 May 2015 08:52:48 -0400 Subject: [PATCH 44/72] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb649e07da5..dc3214c9831 100644 --- a/README.md +++ b/README.md @@ -273,7 +273,7 @@ Note! The templates are included in the library generated. If you want to modi License ------- -Copyright 2015 Reverb Technologies, Inc. +Copyright 2015 SmartBear Software Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From ec08d31031ba540d2beea3767992d9550fe122f8 Mon Sep 17 00:00:00 2001 From: Oleg Godovykh Date: Wed, 29 Apr 2015 17:18:20 -0400 Subject: [PATCH 45/72] add template for Retrofit and Gson --- bin/all-petstore.sh | 1 + bin/retrofit-petstore.sh | 31 +++ .../swagger/codegen/CodegenOperation.java | 2 +- .../languages/RetrofitClientCodegen.java | 190 ++++++++++++++++++ .../com.wordnik.swagger.codegen.CodegenConfig | 1 + .../src/main/resources/retrofit/api.mustache | 29 +++ .../resources/retrofit/bodyParams.mustache | 1 + .../resources/retrofit/formParams.mustache | 1 + .../resources/retrofit/headerParams.mustache | 1 + .../main/resources/retrofit/model.mustache | 50 +++++ .../resources/retrofit/pathParams.mustache | 1 + .../src/main/resources/retrofit/pom.mustache | 143 +++++++++++++ .../resources/retrofit/queryParams.mustache | 1 + .../main/resources/retrofit/service.mustache | 23 +++ pom.xml | 12 ++ .../src/main/java/AndroidManifest.xml | 3 + samples/client/petstore/retrofit/pom.xml | 143 +++++++++++++ .../io/swagger/client/ServiceGenerator.java | 23 +++ .../java/io/swagger/client/api/PetApi.java | 117 +++++++++++ .../java/io/swagger/client/api/StoreApi.java | 60 ++++++ .../java/io/swagger/client/api/UserApi.java | 110 ++++++++++ .../io/swagger/client/model/Category.java | 49 +++++ .../java/io/swagger/client/model/Order.java | 110 ++++++++++ .../java/io/swagger/client/model/Pet.java | 112 +++++++++++ .../java/io/swagger/client/model/Tag.java | 49 +++++ .../java/io/swagger/client/model/User.java | 134 ++++++++++++ .../io/swagger/petstore/test/PetApiTest.java | 158 +++++++++++++++ .../swagger/petstore/test/StoreApiTest.java | 70 +++++++ .../io/swagger/petstore/test/UserApiTest.java | 84 ++++++++ 29 files changed, 1708 insertions(+), 1 deletion(-) create mode 100755 bin/retrofit-petstore.sh create mode 100644 modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/RetrofitClientCodegen.java create mode 100644 modules/swagger-codegen/src/main/resources/retrofit/api.mustache create mode 100644 modules/swagger-codegen/src/main/resources/retrofit/bodyParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/retrofit/formParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/retrofit/headerParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/retrofit/model.mustache create mode 100644 modules/swagger-codegen/src/main/resources/retrofit/pathParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/retrofit/pom.mustache create mode 100644 modules/swagger-codegen/src/main/resources/retrofit/queryParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/retrofit/service.mustache create mode 100644 samples/client/petstore/android-java/src/main/java/AndroidManifest.xml create mode 100644 samples/client/petstore/retrofit/pom.xml create mode 100644 samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java create mode 100644 samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/PetApi.java create mode 100644 samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/StoreApi.java create mode 100644 samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/UserApi.java create mode 100644 samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Category.java create mode 100644 samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Order.java create mode 100644 samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Pet.java create mode 100644 samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Tag.java create mode 100644 samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/User.java create mode 100644 samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/PetApiTest.java create mode 100644 samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/StoreApiTest.java create mode 100644 samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/UserApiTest.java diff --git a/bin/all-petstore.sh b/bin/all-petstore.sh index 0f97790e75a..72797973a32 100755 --- a/bin/all-petstore.sh +++ b/bin/all-petstore.sh @@ -27,6 +27,7 @@ cd $APP_DIR ./bin/qt5-petstore.sh ./bin/php-petstore.sh ./bin/python-petstore.sh +./bin/retrofit-petstore.sh ./bin/ruby-petstore.sh ./bin/objc-petstore.sh ./bin/scala-petstore.sh diff --git a/bin/retrofit-petstore.sh b/bin/retrofit-petstore.sh new file mode 100755 index 00000000000..10b82e61963 --- /dev/null +++ b/bin/retrofit-petstore.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/retrofit -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l retrofit -o samples/client/petstore/retrofit" + +java $JAVA_OPTS -jar $executable $ags diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CodegenOperation.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CodegenOperation.java index 7f8d390f371..76055110b92 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CodegenOperation.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CodegenOperation.java @@ -7,7 +7,7 @@ import java.util.*; public class CodegenOperation { public Boolean hasConsumes, hasProduces, hasParams, returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMapContainer, isListContainer, - hasMore = Boolean.TRUE; + hasMore = Boolean.TRUE, isMultipart; public String path, operationId, returnType, httpMethod, returnBaseType, returnContainer, summary, notes, baseName, defaultResponse; diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/RetrofitClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/RetrofitClientCodegen.java new file mode 100644 index 00000000000..6f80f8a5c5e --- /dev/null +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/RetrofitClientCodegen.java @@ -0,0 +1,190 @@ +package com.wordnik.swagger.codegen.languages; + +import com.wordnik.swagger.codegen.*; +import com.wordnik.swagger.models.Operation; +import com.wordnik.swagger.models.properties.*; + +import java.util.*; +import java.io.File; + +public class RetrofitClientCodegen extends DefaultCodegen implements CodegenConfig { + protected String invokerPackage = "io.swagger.client"; + protected String groupId = "io.swagger"; + protected String artifactId = "swagger-java-client"; + protected String artifactVersion = "1.0.0"; + protected String sourceFolder = "src/main/java"; + + public CodegenType getTag() { + return CodegenType.CLIENT; + } + + public String getName() { + return "retrofit"; + } + + public String getHelp() { + return "Generates a Retrofit client library."; + } + + public RetrofitClientCodegen() { + super(); + outputFolder = "generated-code/java"; + modelTemplateFiles.put("model.mustache", ".java"); + apiTemplateFiles.put("api.mustache", ".java"); + templateDir = "retrofit"; + apiPackage = "io.swagger.client.api"; + modelPackage = "io.swagger.client.model"; + + reservedWords = new HashSet ( + Arrays.asList( + "abstract", "continue", "for", "new", "switch", "assert", + "default", "if", "package", "synchronized", "boolean", "do", "goto", "private", + "this", "break", "double", "implements", "protected", "throw", "byte", "else", + "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", + "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", + "void", "class", "finally", "long", "strictfp", "volatile", "const", "float", + "native", "super", "while") + ); + + additionalProperties.put("invokerPackage", invokerPackage); + additionalProperties.put("groupId", groupId); + additionalProperties.put("artifactId", artifactId); + additionalProperties.put("artifactVersion", artifactVersion); + + supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); + supportingFiles.add(new SupportingFile("service.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ServiceGenerator.java")); + + languageSpecificPrimitives = new HashSet( + Arrays.asList( + "String", + "boolean", + "Boolean", + "Double", + "Integer", + "Long", + "Float", + "Object") + ); + instantiationTypes.put("array", "ArrayList"); + instantiationTypes.put("map", "HashMap"); + } + + @Override + public String escapeReservedWord(String name) { + return "_" + name; + } + + @Override + public String apiFileFolder() { + return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar); + } + + public String modelFileFolder() { + return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); + } + + @Override + public String toVarName(String name) { + // replace - with _ e.g. created-at => created_at + name = name.replaceAll("-", "_"); + + // if it's all uppper case, do nothing + if (name.matches("^[A-Z_]*$")) + return name; + + // camelize (lower first character) the variable name + // pet_id => petId + name = camelize(name, true); + + // for reserved word or word starting with number, append _ + if(reservedWords.contains(name) || name.matches("^\\d.*")) + name = escapeReservedWord(name); + + return name; + } + + @Override + public String toParamName(String name) { + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toModelName(String name) { + // model name cannot use reserved keyword, e.g. return + if(reservedWords.contains(name)) + throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); + + // camelize the model name + // phone_number => PhoneNumber + return camelize(name); + } + + @Override + public String toModelFilename(String name) { + // should be the same as the model name + return toModelName(name); + } + + + @Override + public String getTypeDeclaration(Property p) { + if(p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; + } + else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + + return getSwaggerType(p) + ""; + } + return super.getTypeDeclaration(p); + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + String type = null; + if(typeMapping.containsKey(swaggerType)) { + type = typeMapping.get(swaggerType); + if(languageSpecificPrimitives.contains(type)) + return toModelName(type); + } + else + type = swaggerType; + return toModelName(type); + } + + @Override + public String toOperationId(String operationId) { + // method name cannot use reserved keyword, e.g. return + if(reservedWords.contains(operationId)) + throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); + + return camelize(operationId, true); + } + + public Map postProcessOperations(Map objs) { + Map operations = (Map)objs.get("operations"); + if(operations != null) { + List ops = (List) operations.get("operation"); + for(CodegenOperation operation : ops) { + if (operation.hasConsumes == Boolean.TRUE) { + Map firstType = operation.consumes.get(0); + if (firstType != null) { + if ("multipart/form-data".equals(firstType.get("mediaType"))) { + operation.isMultipart = Boolean.TRUE; + } + } + } + if(operation.returnType == null) { + operation.returnType = "Void"; + } + } + } + return objs; + } +} diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig index 73dbeae62ef..4dec8a51df5 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig @@ -10,6 +10,7 @@ com.wordnik.swagger.codegen.languages.PhpClientCodegen com.wordnik.swagger.codegen.languages.PythonClientCodegen com.wordnik.swagger.codegen.languages.Python3ClientCodegen com.wordnik.swagger.codegen.languages.Qt5CPPGenerator +com.wordnik.swagger.codegen.languages.RetrofitClientCodegen com.wordnik.swagger.codegen.languages.RubyClientCodegen com.wordnik.swagger.codegen.languages.ScalaClientCodegen com.wordnik.swagger.codegen.languages.ScalatraServerCodegen diff --git a/modules/swagger-codegen/src/main/resources/retrofit/api.mustache b/modules/swagger-codegen/src/main/resources/retrofit/api.mustache new file mode 100644 index 00000000000..a916f363ff5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/retrofit/api.mustache @@ -0,0 +1,29 @@ +package {{package}}; + +import {{modelPackage}}.*; + +import retrofit.http.*; +import retrofit.mime.*; +import java.util.*; + +{{#imports}}import {{import}}; +{{/imports}} + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} * @param {{paramName}} {{description}} +{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} + */ + {{#formParams}}{{#-first}} + {{#isMultipart}}@Multipart{{/isMultipart}}{{^isMultipart}}@FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} + @{{httpMethod}}("{{path}}") + {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}} {{nickname}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{^hasMore}} + );{{/hasMore}}{{/allParams}} + {{/operation}} +} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/retrofit/bodyParams.mustache b/modules/swagger-codegen/src/main/resources/retrofit/bodyParams.mustache new file mode 100644 index 00000000000..f8788583db5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/retrofit/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}@Body {{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/retrofit/formParams.mustache b/modules/swagger-codegen/src/main/resources/retrofit/formParams.mustache new file mode 100644 index 00000000000..9853bc0bf11 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/retrofit/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{#notFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{paramName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{paramName}}") TypedFile {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/retrofit/headerParams.mustache b/modules/swagger-codegen/src/main/resources/retrofit/headerParams.mustache new file mode 100644 index 00000000000..29206e1546b --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/retrofit/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@Header("{{baseName}}") {{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/retrofit/model.mustache b/modules/swagger-codegen/src/main/resources/retrofit/model.mustache new file mode 100644 index 00000000000..f4446d5a1ef --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/retrofit/model.mustache @@ -0,0 +1,50 @@ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import com.wordnik.swagger.annotations.*; +import com.google.gson.annotations.SerializedName; +{{#models}} + +{{#model}}{{#description}} +/** + * {{description}} + **/{{/description}} +@ApiModel(description = "{{{description}}}") +public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} { + {{#vars}}{{#isEnum}} + public enum {{datatypeWithEnum}} { + {{#allowableValues}}{{#values}} {{.}}, {{/values}}{{/allowableValues}} + };{{/isEnum}} + + /**{{#description}} + * {{{description}}}{{/description}}{{#minimum}} + * minimum: {{minimum}}{{/minimum}}{{#maximum}} + * maximum: {{maximum}}{{/maximum}} + **/ + @ApiModelProperty({{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") + @SerializedName("{{baseName}}"){{#isEnum}} + private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}};{{/isEnum}}{{^isEnum}} + private {{{datatype}}} {{name}} = {{{defaultValue}}};{{/isEnum}}{{/vars}} + + {{#vars}} + public {{{datatypeWithEnum}}} {{getter}}() { + return {{name}}; + } + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + } + {{/vars}} + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}}sb.append(" " + super.toString()).append("\n");{{/parent}} + {{#vars}}sb.append(" {{name}}: ").append({{name}}).append("\n"); + {{/vars}}sb.append("}\n"); + return sb.toString(); + } +} +{{/model}} +{{/models}} diff --git a/modules/swagger-codegen/src/main/resources/retrofit/pathParams.mustache b/modules/swagger-codegen/src/main/resources/retrofit/pathParams.mustache new file mode 100644 index 00000000000..8a8bdc74c88 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/retrofit/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}@Path("{{baseName}}") {{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/retrofit/pom.mustache b/modules/swagger-codegen/src/main/resources/retrofit/pom.mustache new file mode 100644 index 00000000000..fd631871054 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/retrofit/pom.mustache @@ -0,0 +1,143 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + + scm:git:git@github.com:wordnik/swagger-mustache.git + scm:git:git@github.com:wordnik/swagger-codegen.git + https://github.com/wordnik/swagger-codegen + + + 2.2.0 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + + + com.wordnik + swagger-annotations + ${swagger-annotations-version} + + + com.google.code.gson + gson + ${gson-version} + compile + + + com.squareup.retrofit + retrofit + ${retrofit-version} + compile + + + + + junit + junit + ${junit-version} + test + + + + 1.5.3-M1 + 2.3.1 + 1.9.0 + 1.0.0 + 4.12 + + diff --git a/modules/swagger-codegen/src/main/resources/retrofit/queryParams.mustache b/modules/swagger-codegen/src/main/resources/retrofit/queryParams.mustache new file mode 100644 index 00000000000..e0a58533e5f --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/retrofit/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}@Query("{{baseName}}") {{{dataType}}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/retrofit/service.mustache b/modules/swagger-codegen/src/main/resources/retrofit/service.mustache new file mode 100644 index 00000000000..218a9304071 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/retrofit/service.mustache @@ -0,0 +1,23 @@ +package {{invokerPackage}}; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import retrofit.RestAdapter; +import retrofit.converter.GsonConverter; + +public class ServiceGenerator { + // No need to instantiate this class. + private ServiceGenerator() { } + + public static S createService(Class serviceClass) { + Gson gson = new GsonBuilder() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") + .create(); + RestAdapter adapter = new RestAdapter.Builder() + .setEndpoint("{{basePath}}") + .setConverter(new GsonConverter(gson)) + .build(); + + return adapter.create(serviceClass); + } +} diff --git a/pom.xml b/pom.xml index 6fbb36464f8..c8d223cfb2c 100644 --- a/pom.xml +++ b/pom.xml @@ -350,6 +350,18 @@ samples/client/petstore/ruby + + retrofit-client + + + env + java + + + + samples/client/petstore/retrofit + + spring-mvc diff --git a/samples/client/petstore/android-java/src/main/java/AndroidManifest.xml b/samples/client/petstore/android-java/src/main/java/AndroidManifest.xml new file mode 100644 index 00000000000..3042699fd86 --- /dev/null +++ b/samples/client/petstore/android-java/src/main/java/AndroidManifest.xml @@ -0,0 +1,3 @@ + + + diff --git a/samples/client/petstore/retrofit/pom.xml b/samples/client/petstore/retrofit/pom.xml new file mode 100644 index 00000000000..4a95855cac9 --- /dev/null +++ b/samples/client/petstore/retrofit/pom.xml @@ -0,0 +1,143 @@ + + 4.0.0 + io.swagger + swagger-java-client + jar + swagger-java-client + 1.0.0 + + scm:git:git@github.com:wordnik/swagger-mustache.git + scm:git:git@github.com:wordnik/swagger-codegen.git + https://github.com/wordnik/swagger-codegen + + + 2.2.0 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + + + com.wordnik + swagger-annotations + ${swagger-annotations-version} + + + com.google.code.gson + gson + ${gson-version} + compile + + + com.squareup.retrofit + retrofit + ${retrofit-version} + compile + + + + + junit + junit + ${junit-version} + test + + + + 1.5.3-M1 + 2.3.1 + 1.9.0 + 1.0.0 + 4.12 + + diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java new file mode 100644 index 00000000000..e443c984fd0 --- /dev/null +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java @@ -0,0 +1,23 @@ +package io.swagger.client; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import retrofit.RestAdapter; +import retrofit.converter.GsonConverter; + +public class ServiceGenerator { + // No need to instantiate this class. + private ServiceGenerator() { } + + public static S createService(Class serviceClass) { + Gson gson = new GsonBuilder() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") + .create(); + RestAdapter adapter = new RestAdapter.Builder() + .setEndpoint("http://petstore.swagger.io/v2") + .setConverter(new GsonConverter(gson)) + .build(); + + return adapter.create(serviceClass); + } +} diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/PetApi.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/PetApi.java new file mode 100644 index 00000000000..3d1b0893b61 --- /dev/null +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/PetApi.java @@ -0,0 +1,117 @@ +package io.swagger.client.api; + +import io.swagger.client.model.*; + +import retrofit.http.*; +import retrofit.mime.*; +import java.util.*; + +import io.swagger.client.model.Pet; +import java.io.File; + +public interface PetApi { + + /** + * Update an existing pet + * + * @param body Pet object that needs to be added to the store + * @return Void + */ + + @PUT("/pet") + Void updatePet( + @Body Pet body + ); + + /** + * Add a new pet to the store + * + * @param body Pet object that needs to be added to the store + * @return Void + */ + + @POST("/pet") + Void addPet( + @Body Pet body + ); + + /** + * Finds Pets by status + * Multiple status values can be provided with comma seperated strings + * @param status Status values that need to be considered for filter + * @return List + */ + + @GET("/pet/findByStatus") + List findPetsByStatus( + @Query("status") List status + ); + + /** + * Finds Pets by tags + * Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing. + * @param tags Tags to filter by + * @return List + */ + + @GET("/pet/findByTags") + List findPetsByTags( + @Query("tags") List tags + ); + + /** + * Find pet by ID + * Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions + * @param petId ID of pet that needs to be fetched + * @return Pet + */ + + @GET("/pet/{petId}") + Pet getPetById( + @Path("petId") Long petId + ); + + /** + * Updates a pet in the store with form data + * + * @param petId ID of pet that needs to be updated + * @param name Updated name of the pet + * @param status Updated status of the pet + * @return Void + */ + + @FormUrlEncoded + @POST("/pet/{petId}") + Void updatePetWithForm( + @Path("petId") String petId,@Field("name") String name,@Field("status") String status + ); + + /** + * Deletes a pet + * + * @param apiKey + * @param petId Pet id to delete + * @return Void + */ + + @DELETE("/pet/{petId}") + Void deletePet( + @Header("api_key") String apiKey,@Path("petId") Long petId + ); + + /** + * uploads an image + * + * @param petId ID of pet to update + * @param additionalMetadata Additional data to pass to server + * @param file file to upload + * @return Void + */ + + @Multipart + @POST("/pet/{petId}/uploadImage") + Void uploadFile( + @Path("petId") Long petId,@Part("additionalMetadata") String additionalMetadata,@Part("file") TypedFile file + ); + +} diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/StoreApi.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/StoreApi.java new file mode 100644 index 00000000000..fcd47b4b735 --- /dev/null +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/StoreApi.java @@ -0,0 +1,60 @@ +package io.swagger.client.api; + +import io.swagger.client.model.*; + +import retrofit.http.*; +import retrofit.mime.*; +import java.util.*; + +import java.util.Map; +import io.swagger.client.model.Order; + +public interface StoreApi { + + /** + * Returns pet inventories by status + * Returns a map of status codes to quantities + * @return Map + */ + + @GET("/store/inventory") + Map getInventory(); + + + /** + * Place an order for a pet + * + * @param body order placed for purchasing the pet + * @return Order + */ + + @POST("/store/order") + Order placeOrder( + @Body Order body + ); + + /** + * Find purchase order by ID + * For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + * @param orderId ID of pet that needs to be fetched + * @return Order + */ + + @GET("/store/order/{orderId}") + Order getOrderById( + @Path("orderId") String orderId + ); + + /** + * Delete purchase order by ID + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + * @param orderId ID of the order that needs to be deleted + * @return Void + */ + + @DELETE("/store/order/{orderId}") + Void deleteOrder( + @Path("orderId") String orderId + ); + +} diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/UserApi.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/UserApi.java new file mode 100644 index 00000000000..4aa39c52e2c --- /dev/null +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/UserApi.java @@ -0,0 +1,110 @@ +package io.swagger.client.api; + +import io.swagger.client.model.*; + +import retrofit.http.*; +import retrofit.mime.*; +import java.util.*; + +import io.swagger.client.model.User; +import java.util.*; + +public interface UserApi { + + /** + * Create user + * This can only be done by the logged in user. + * @param body Created user object + * @return Void + */ + + @POST("/user") + Void createUser( + @Body User body + ); + + /** + * Creates list of users with given input array + * + * @param body List of user object + * @return Void + */ + + @POST("/user/createWithArray") + Void createUsersWithArrayInput( + @Body List body + ); + + /** + * Creates list of users with given input array + * + * @param body List of user object + * @return Void + */ + + @POST("/user/createWithList") + Void createUsersWithListInput( + @Body List body + ); + + /** + * Logs user into the system + * + * @param username The user name for login + * @param password The password for login in clear text + * @return String + */ + + @GET("/user/login") + String loginUser( + @Query("username") String username,@Query("password") String password + ); + + /** + * Logs out current logged in user session + * + * @return Void + */ + + @GET("/user/logout") + Void logoutUser(); + + + /** + * Get user by user name + * + * @param username The name that needs to be fetched. Use user1 for testing. + * @return User + */ + + @GET("/user/{username}") + User getUserByName( + @Path("username") String username + ); + + /** + * Updated user + * This can only be done by the logged in user. + * @param username name that need to be deleted + * @param body Updated user object + * @return Void + */ + + @PUT("/user/{username}") + Void updateUser( + @Path("username") String username,@Body User body + ); + + /** + * Delete user + * This can only be done by the logged in user. + * @param username The name that needs to be deleted + * @return Void + */ + + @DELETE("/user/{username}") + Void deleteUser( + @Path("username") String username + ); + +} diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Category.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Category.java new file mode 100644 index 00000000000..8ba10d629dc --- /dev/null +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Category.java @@ -0,0 +1,49 @@ +package io.swagger.client.model; + + +import com.wordnik.swagger.annotations.*; +import com.google.gson.annotations.SerializedName; + + +@ApiModel(description = "") +public class Category { + + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("id") + private Long id = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("name") + private String name = null; + + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Category {\n"); + + sb.append(" id: ").append(id).append("\n"); + sb.append(" name: ").append(name).append("\n"); + sb.append("}\n"); + return sb.toString(); + } +} diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Order.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Order.java new file mode 100644 index 00000000000..d7d0b2d9282 --- /dev/null +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Order.java @@ -0,0 +1,110 @@ +package io.swagger.client.model; + +import java.util.Date; + +import com.wordnik.swagger.annotations.*; +import com.google.gson.annotations.SerializedName; + + +@ApiModel(description = "") +public class Order { + + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("id") + private Long id = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("petId") + private Long petId = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("quantity") + private Integer quantity = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("shipDate") + private Date shipDate = null; + public enum StatusEnum { + placed, approved, delivered, + }; + + /** + * Order Status + **/ + @ApiModelProperty(value = "Order Status") + @SerializedName("status") + private StatusEnum status = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("complete") + private Boolean complete = null; + + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + public Long getPetId() { + return petId; + } + public void setPetId(Long petId) { + this.petId = petId; + } + + public Integer getQuantity() { + return quantity; + } + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + public Date getShipDate() { + return shipDate; + } + public void setShipDate(Date shipDate) { + this.shipDate = shipDate; + } + + public StatusEnum getStatus() { + return status; + } + public void setStatus(StatusEnum status) { + this.status = status; + } + + public Boolean getComplete() { + return complete; + } + public void setComplete(Boolean complete) { + this.complete = complete; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Order {\n"); + + sb.append(" id: ").append(id).append("\n"); + sb.append(" petId: ").append(petId).append("\n"); + sb.append(" quantity: ").append(quantity).append("\n"); + sb.append(" shipDate: ").append(shipDate).append("\n"); + sb.append(" status: ").append(status).append("\n"); + sb.append(" complete: ").append(complete).append("\n"); + sb.append("}\n"); + return sb.toString(); + } +} diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Pet.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Pet.java new file mode 100644 index 00000000000..66a02367c90 --- /dev/null +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Pet.java @@ -0,0 +1,112 @@ +package io.swagger.client.model; + +import io.swagger.client.model.Category; +import java.util.*; +import io.swagger.client.model.Tag; + +import com.wordnik.swagger.annotations.*; +import com.google.gson.annotations.SerializedName; + + +@ApiModel(description = "") +public class Pet { + + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("id") + private Long id = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("category") + private Category category = null; + + /** + **/ + @ApiModelProperty(required = true, value = "") + @SerializedName("name") + private String name = null; + + /** + **/ + @ApiModelProperty(required = true, value = "") + @SerializedName("photoUrls") + private List photoUrls = new ArrayList() ; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("tags") + private List tags = new ArrayList() ; + public enum StatusEnum { + available, pending, sold, + }; + + /** + * pet status in the store + **/ + @ApiModelProperty(value = "pet status in the store") + @SerializedName("status") + private StatusEnum status = null; + + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + public Category getCategory() { + return category; + } + public void setCategory(Category category) { + this.category = category; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public List getPhotoUrls() { + return photoUrls; + } + public void setPhotoUrls(List photoUrls) { + this.photoUrls = photoUrls; + } + + public List getTags() { + return tags; + } + public void setTags(List tags) { + this.tags = tags; + } + + public StatusEnum getStatus() { + return status; + } + public void setStatus(StatusEnum status) { + this.status = status; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Pet {\n"); + + sb.append(" id: ").append(id).append("\n"); + sb.append(" category: ").append(category).append("\n"); + sb.append(" name: ").append(name).append("\n"); + sb.append(" photoUrls: ").append(photoUrls).append("\n"); + sb.append(" tags: ").append(tags).append("\n"); + sb.append(" status: ").append(status).append("\n"); + sb.append("}\n"); + return sb.toString(); + } +} diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Tag.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Tag.java new file mode 100644 index 00000000000..e6ddd4c92cd --- /dev/null +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Tag.java @@ -0,0 +1,49 @@ +package io.swagger.client.model; + + +import com.wordnik.swagger.annotations.*; +import com.google.gson.annotations.SerializedName; + + +@ApiModel(description = "") +public class Tag { + + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("id") + private Long id = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("name") + private String name = null; + + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Tag {\n"); + + sb.append(" id: ").append(id).append("\n"); + sb.append(" name: ").append(name).append("\n"); + sb.append("}\n"); + return sb.toString(); + } +} diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/User.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/User.java new file mode 100644 index 00000000000..f42f77b9773 --- /dev/null +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/User.java @@ -0,0 +1,134 @@ +package io.swagger.client.model; + + +import com.wordnik.swagger.annotations.*; +import com.google.gson.annotations.SerializedName; + + +@ApiModel(description = "") +public class User { + + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("id") + private Long id = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("username") + private String username = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("firstName") + private String firstName = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("lastName") + private String lastName = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("email") + private String email = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("password") + private String password = null; + + /** + **/ + @ApiModelProperty(value = "") + @SerializedName("phone") + private String phone = null; + + /** + * User Status + **/ + @ApiModelProperty(value = "User Status") + @SerializedName("userStatus") + private Integer userStatus = null; + + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + public String getPhone() { + return phone; + } + public void setPhone(String phone) { + this.phone = phone; + } + + public Integer getUserStatus() { + return userStatus; + } + public void setUserStatus(Integer userStatus) { + this.userStatus = userStatus; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class User {\n"); + + sb.append(" id: ").append(id).append("\n"); + sb.append(" username: ").append(username).append("\n"); + sb.append(" firstName: ").append(firstName).append("\n"); + sb.append(" lastName: ").append(lastName).append("\n"); + sb.append(" email: ").append(email).append("\n"); + sb.append(" password: ").append(password).append("\n"); + sb.append(" phone: ").append(phone).append("\n"); + sb.append(" userStatus: ").append(userStatus).append("\n"); + sb.append("}\n"); + return sb.toString(); + } +} diff --git a/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/PetApiTest.java b/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/PetApiTest.java new file mode 100644 index 00000000000..c588a04adcc --- /dev/null +++ b/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/PetApiTest.java @@ -0,0 +1,158 @@ +package io.swagger.petstore.test; + +import io.swagger.client.ServiceGenerator; +import io.swagger.client.api.*; +import io.swagger.client.model.*; + +import retrofit.RetrofitError; +import retrofit.mime.TypedFile; + +import java.util.*; +import java.io.*; + +import static org.junit.Assert.*; +import org.junit.*; + +public class PetApiTest { + PetApi api = null; + + @Before + public void setup() { + api = ServiceGenerator.createService(PetApi.class); + } + + @Test + public void testCreateAndGetPet() throws Exception { + Pet pet = createRandomPet(); + api.addPet(pet); + + Pet fetched = api.getPetById(pet.getId()); + assertNotNull(fetched); + assertEquals(pet.getId(), fetched.getId()); + assertNotNull(fetched.getCategory()); + assertEquals(fetched.getCategory().getName(), pet.getCategory().getName()); + } + + @Test + public void testUpdatePet() throws Exception { + Pet pet = createRandomPet(); + pet.setName("programmer"); + + api.updatePet(pet); + + Pet fetched = api.getPetById(pet.getId()); + assertNotNull(fetched); + assertEquals(pet.getId(), fetched.getId()); + assertNotNull(fetched.getCategory()); + assertEquals(fetched.getCategory().getName(), pet.getCategory().getName()); + } + + @Test + public void testFindPetsByStatus() throws Exception { + Pet pet = createRandomPet(); + pet.setName("programmer"); + pet.setStatus(Pet.StatusEnum.available); + + api.updatePet(pet); + + List pets = api.findPetsByStatus(Arrays.asList(new String[]{"available"})); + assertNotNull(pets); + + boolean found = false; + for(Pet fetched : pets) { + if(fetched.getId().equals(pet.getId())) { + found = true; + break; + } + } + + assertTrue(found); + } + + @Test + public void testFindPetsByTags() throws Exception { + Pet pet = createRandomPet(); + pet.setName("monster"); + pet.setStatus(Pet.StatusEnum.available); + + List tags = new ArrayList(); + Tag tag1 = new Tag(); + tag1.setName("friendly"); + tags.add(tag1); + pet.setTags(tags); + + api.updatePet(pet); + + List pets = api.findPetsByTags(Arrays.asList(new String[]{"friendly"})); + assertNotNull(pets); + + boolean found = false; + for(Pet fetched : pets) { + if(fetched.getId().equals(pet.getId())) { + found = true; + break; + } + } + assertTrue(found); + } + + @Test + public void testUpdatePetWithForm() throws Exception { + Pet pet = createRandomPet(); + pet.setName("frank"); + api.addPet(pet); + + Pet fetched = api.getPetById(pet.getId()); + + api.updatePetWithForm(String.valueOf(fetched.getId()), "furt", null); + Pet updated = api.getPetById(fetched.getId()); + + assertEquals(updated.getName(), fetched.getName()); + } + + @Test + public void testDeletePet() throws Exception { + Pet pet = createRandomPet(); + api.addPet(pet); + + Pet fetched = api.getPetById(pet.getId()); + api.deletePet(null, fetched.getId()); + + try { + fetched = api.getPetById(fetched.getId()); + fail("expected an error"); + } + catch (RetrofitError e) { + assertEquals(404, e.getResponse().getStatus()); + } + } + + @Test + public void testUploadFile() throws Exception { + Pet pet = createRandomPet(); + api.addPet(pet); + + File file = new File("hello.txt"); + BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + writer.write("Hello world!"); + writer.close(); + + api.uploadFile(pet.getId(), "a test file", new TypedFile("text/plain", file)); + } + + private Pet createRandomPet() { + Pet pet = new Pet(); + pet.setId(System.currentTimeMillis()); + pet.setName("gorilla"); + + Category category = new Category(); + category.setName("really-happy"); + + pet.setCategory(category); + pet.setStatus(Pet.StatusEnum.available); + List photos = Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"}); + pet.setPhotoUrls(photos); + + return pet; + } +} \ No newline at end of file diff --git a/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/StoreApiTest.java b/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/StoreApiTest.java new file mode 100644 index 00000000000..733b597fefc --- /dev/null +++ b/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/StoreApiTest.java @@ -0,0 +1,70 @@ +package io.swagger.petstore.test; + +import io.swagger.client.ServiceGenerator; +import io.swagger.client.api.*; +import io.swagger.client.model.*; + +import retrofit.RetrofitError; + +import java.util.*; +import java.io.*; + +import static org.junit.Assert.*; +import org.junit.*; + +public class StoreApiTest { + StoreApi api = null; + + @Before + public void setup() { + api = ServiceGenerator.createService(StoreApi.class); + } + + @Test + public void testGetInventory() throws Exception { + Map inventory = api.getInventory(); + assertTrue(inventory.keySet().size() > 0); + } + + @Test + public void testPlaceOrder() throws Exception { + Order order = createOrder(); + api.placeOrder(order); + + Order fetched = api.getOrderById(String.valueOf(order.getId())); + assertEquals(order.getId(), fetched.getId()); + assertEquals(order.getPetId(), fetched.getPetId()); + assertEquals(order.getQuantity(), fetched.getQuantity()); + } + + @Test + public void testDeleteOrder() throws Exception { + Order order = createOrder(); + api.placeOrder(order); + + Order fetched = api.getOrderById(String.valueOf(order.getId())); + assertEquals(fetched.getId(), order.getId()); + + api.deleteOrder(String.valueOf(order.getId())); + + try { + api.getOrderById(String.valueOf(order.getId())); + // fail("expected an error"); + } + catch (RetrofitError e) { + // ok + } + } + + private Order createOrder() { + Order order = new Order(); + order.setId(new Long(System.currentTimeMillis())); + order.setPetId(new Long(200)); + order.setQuantity(new Integer(13)); + order.setShipDate(new java.util.Date()); + order.setStatus(Order.StatusEnum.placed); + order.setComplete(true); + + return order; + } +} \ No newline at end of file diff --git a/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/UserApiTest.java b/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/UserApiTest.java new file mode 100644 index 00000000000..c7748bc492d --- /dev/null +++ b/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/UserApiTest.java @@ -0,0 +1,84 @@ +package io.swagger.petstore.test; + +import io.swagger.client.ServiceGenerator; +import io.swagger.client.api.*; +import io.swagger.client.model.*; + +import java.util.*; +import java.io.*; + +import static org.junit.Assert.*; +import org.junit.*; + +public class UserApiTest { + UserApi api = null; + + @Before + public void setup() { + api = ServiceGenerator.createService(UserApi.class); + } + + @Test + public void testCreateUser() throws Exception { + User user = createUser(); + + api.createUser(user); + + User fetched = api.getUserByName(user.getUsername()); + assertEquals(user.getId(), fetched.getId()); + } + + @Test + public void testCreateUsersWithArray() throws Exception { + User user1 = createUser(); + user1.setUsername("abc123"); + User user2 = createUser(); + user2.setUsername("123abc"); + + api.createUsersWithArrayInput(Arrays.asList(new User[]{user1, user2})); + + User fetched = api.getUserByName(user1.getUsername()); + assertEquals(user1.getId(), fetched.getId()); + } + + @Test + public void testCreateUsersWithList() throws Exception { + User user1 = createUser(); + user1.setUsername("abc123"); + User user2 = createUser(); + user2.setUsername("123abc"); + + api.createUsersWithListInput(Arrays.asList(new User[]{user1, user2})); + + User fetched = api.getUserByName(user1.getUsername()); + assertEquals(user1.getId(), fetched.getId()); + } + + @Test + public void testLoginUser() throws Exception { + User user = createUser(); + api.createUser(user); + + String token = api.loginUser(user.getUsername(), user.getPassword()); + assertTrue(token.startsWith("logged in user session:")); + } + + @Test + public void logoutUser() throws Exception { + api.logoutUser(); + } + + private User createUser() { + User user = new User(); + user.setId(System.currentTimeMillis()); + user.setUsername("fred"); + user.setFirstName("Fred"); + user.setLastName("Meyer"); + user.setEmail("fred@fredmeyer.com"); + user.setPassword("xxXXxx"); + user.setPhone("408-867-5309"); + user.setUserStatus(123); + + return user; + } +} \ No newline at end of file From 0996901e72ef510c591fafacdbbeb38d1b4a3bd9 Mon Sep 17 00:00:00 2001 From: Richie Azaria Date: Fri, 29 May 2015 13:01:42 -0700 Subject: [PATCH 46/72] add documentation -c option and config-help --- README.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cb649e07da5..da7d0752f0d 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,8 @@ NAME SYNOPSIS swagger generate [(-a | --auth )] + [(-c | --config )] + [-D ] (-i | --input-spec ) (-l | --lang ) [(-o | --output )] @@ -72,6 +74,16 @@ OPTIONS remotely. Pass in a URL-encoded string of name:header with a comma separating multiple values + -c , --config + Path to json configuration file. File content should be in a json + format {"optionKey":"optionValue", "optionKey1":"optionValue1"...} + Supported options can be different for each language. Run + config-help -l {lang} command for language specific config options. + + -D + sets specified system properties in the format of + name=value,name=value + -i , --input-spec location of the swagger spec, as URL or file (required) @@ -166,8 +178,60 @@ SwaggerYamlGenerator.java TizenClientCodegen.java ``` -Each of these files creates reasonable defaults so you can get running quickly. But if you want to configure package names, prefixes, model folders, etc., you may want to extend these. +Each of these files creates reasonable defaults so you can get running quickly. But if you want to configure package names, prefixes, model folders, etc. you can use a json config file to pass the values. +``` +java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \ + -i http://petstore.swagger.io/v2/swagger.json \ + -l java \ + -o samples/client/petstore/java \ + -c path/to/config.json +``` +Supported config options can be different per language. Running `config-help -l {lang}` will show available options. + +``` +java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jarr config-help -l java +``` + +Output + +``` +CONFIG OPTIONS + modelPackage + package for generated models + + apiPackage + package for generated api classes + + invokerPackage + root package for generated code + + groupId + groupId in generated pom.xml + + artifactId + artifactId in generated pom.xml + + artifactVersion + artifact version in generated pom.xml + + sourceFolder + source folder for generated code +``` + +Your config file for java can look like + +``` +{ + "groupId":"com.my.company", + "artifactId":"MyClent", + "artifactVersion":"1.2.0" +} +``` + +For all the unspecified options default values will be used. + +Another way to override default options is to extend config class for specific language. To change, for example, the prefix for the Objective-C generated files, simply subclass the ObjcClientCodegen.java: ``` From b5429d9e8ec2afe852980551443defc7f5c9e1d0 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Sat, 30 May 2015 18:04:20 +0800 Subject: [PATCH 47/72] Added authentication for objc client. --- .../codegen/languages/ObjcClientCodegen.java | 2 + .../src/main/resources/objc/SWGApiClient.h | 15 +++ .../src/main/resources/objc/SWGApiClient.m | 58 ++++++++- .../objc/SWGConfiguration-body.mustache | 91 ++++++++++++++ .../objc/SWGConfiguration-header.mustache | 51 ++++++++ .../resources/objc/SWGQueryParamCollection.m | 2 +- .../src/main/resources/objc/api-body.mustache | 5 + .../main/resources/objc/api-header.mustache | 1 + .../apiBodyResponseWithContainer.mustache | 1 + .../objc/apiNonPrimitiveResponse.mustache | 1 + .../objc/apiPrimitiveResponse.mustache | 1 + .../main/resources/objc/voidResponse.mustache | 1 + .../PetstoreClient.xcodeproj/project.pbxproj | 6 + .../xcschemes/PetstoreClient.xcscheme | 112 ++++++++++++++++++ .../xcschemes/xcschememanagement.plist | 27 +++++ .../PetstoreClient/ViewController.m | 9 ++ .../PetstoreClientTests/SWGApiClientTest.m | 44 ++++++- samples/client/petstore/objc/Podfile.lock | 4 +- .../petstore/objc/client/SWGApiClient.h | 15 +++ .../petstore/objc/client/SWGApiClient.m | 58 ++++++++- .../petstore/objc/client/SWGConfiguration.h | 51 ++++++++ .../petstore/objc/client/SWGConfiguration.m | 91 ++++++++++++++ .../client/petstore/objc/client/SWGPetApi.m | 34 ++++++ .../objc/client/SWGQueryParamCollection.m | 2 +- .../client/petstore/objc/client/SWGStoreApi.h | 1 + .../client/petstore/objc/client/SWGStoreApi.m | 18 +++ .../client/petstore/objc/client/SWGUserApi.h | 1 + .../client/petstore/objc/client/SWGUserApi.m | 34 ++++++ 28 files changed, 721 insertions(+), 15 deletions(-) create mode 100644 modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-body.mustache create mode 100644 modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-header.mustache create mode 100644 samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/PetstoreClient.xcscheme create mode 100644 samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 samples/client/petstore/objc/client/SWGConfiguration.h create mode 100644 samples/client/petstore/objc/client/SWGConfiguration.m diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java index d1e227ce744..9020a5f8170 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java @@ -122,6 +122,8 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { supportingFiles.add(new SupportingFile("SWGFile.m", sourceFolder, "SWGFile.m")); supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", sourceFolder, "JSONValueTransformer+ISO8601.m")); supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", sourceFolder, "JSONValueTransformer+ISO8601.h")); + supportingFiles.add(new SupportingFile("SWGConfiguration-body.mustache", sourceFolder, "SWGConfiguration.m")); + supportingFiles.add(new SupportingFile("SWGConfiguration-header.mustache", sourceFolder, "SWGConfiguration.h")); supportingFiles.add(new SupportingFile("Podfile.mustache", "", "Podfile")); } diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h index cd6f52db5c6..d1f9203f180 100644 --- a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h +++ b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h @@ -54,11 +54,16 @@ extern NSString *const SWGResponseObjectErrorKey; -(void)setHeaderValue:(NSString*) value forKey:(NSString*) forKey; +- (void) updateHeaderParams:(NSDictionary **)headers + queryParams:(NSDictionary **)querys + WithAuthSettings:(NSArray *)authSettings; + -(NSNumber*) dictionary:(NSString*) path method:(NSString*) method queryParams:(NSDictionary*) queryParams body:(id) body headerParams:(NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType:(NSString*) requestContentType responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSDictionary*, NSError *))completionBlock; @@ -68,8 +73,18 @@ extern NSString *const SWGResponseObjectErrorKey; queryParams:(NSDictionary*) queryParams body:(id) body headerParams:(NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType:(NSString*) requestContentType responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSString*, NSError *))completionBlock; @end + + + + + + + + + diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m index b38b02e0e03..5e2985bbe79 100644 --- a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m +++ b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m @@ -1,6 +1,7 @@ #import "SWGApiClient.h" #import "SWGFile.h" #import "SWGQueryParamCollection.h" +#import "SWGConfiguration.h" @implementation SWGApiClient @@ -15,10 +16,22 @@ static NSOperationQueue* sharedQueue; static void (^reachabilityChangeBlock)(int); static bool loggingEnabled = true; +#pragma mark - Log Methods + +(void)setLoggingEnabled:(bool) state { loggingEnabled = state; } +- (void)logRequest:(NSURLRequest*)request { + NSLog(@"request: %@", [self descriptionForRequest:request]); +} + +- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error { + NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data ); +} + +#pragma mark - + +(void)clearCache { [[NSURLCache sharedURLCache] removeAllCachedResponses]; } @@ -305,19 +318,47 @@ static bool loggingEnabled = true; return [[request URL] absoluteString]; } -- (void)logRequest:(NSURLRequest*)request { - NSLog(@"request: %@", [self descriptionForRequest:request]); + +/** + * Update header and query params based on authentication settings + */ +- (void) updateHeaderParams:(NSDictionary *__autoreleasing *)headers + queryParams:(NSDictionary *__autoreleasing *)querys + WithAuthSettings:(NSArray *)authSettings { + + if (!authSettings || [authSettings count] == 0) { + return; + } + + NSMutableDictionary *headersWithAuth = [NSMutableDictionary dictionaryWithDictionary:*headers]; + NSMutableDictionary *querysWithAuth = [NSMutableDictionary dictionaryWithDictionary:*querys]; + + SWGConfiguration *config = [SWGConfiguration sharedConfig]; + for (NSString *auth in authSettings) { + NSDictionary *authSetting = [[config authSettings] objectForKey:auth]; + + if (authSetting) { + if ([authSetting[@"in"] isEqualToString:@"header"]) { + [headersWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]]; + } + else if ([authSetting[@"in"] isEqualToString:@"query"]) { + [querysWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]]; + } + } + } + + *headers = [NSDictionary dictionaryWithDictionary:headersWithAuth]; + *querys = [NSDictionary dictionaryWithDictionary:querysWithAuth]; } -- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error { - NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data ); -} +#pragma mark - Perform Request Methods -(NSNumber*) dictionary: (NSString*) path method: (NSString*) method queryParams: (NSDictionary*) queryParams body: (id) body headerParams: (NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType: (NSString*) requestContentType responseContentType: (NSString*) responseContentType completionBlock: (void (^)(NSDictionary*, NSError *))completionBlock { @@ -342,6 +383,9 @@ static bool loggingEnabled = true; else { self.responseSerializer = [AFHTTPResponseSerializer serializer]; } + + // auth setting + [self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings]; NSMutableURLRequest * request = nil; if (body != nil && [body isKindOfClass:[NSArray class]]){ @@ -476,6 +520,7 @@ static bool loggingEnabled = true; queryParams: (NSDictionary*) queryParams body: (id) body headerParams: (NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType: (NSString*) requestContentType responseContentType: (NSString*) responseContentType completionBlock: (void (^)(NSString*, NSError *))completionBlock { @@ -500,6 +545,9 @@ static bool loggingEnabled = true; else { self.responseSerializer = [AFHTTPResponseSerializer serializer]; } + + // auth setting + [self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings]; NSMutableURLRequest * request = nil; if (body != nil && [body isKindOfClass:[NSArray class]]){ diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-body.mustache b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-body.mustache new file mode 100644 index 00000000000..b326244fe0a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-body.mustache @@ -0,0 +1,91 @@ +#import "SWGConfiguration.h" + +@interface SWGConfiguration () + +@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKey; +@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKeyPrefix; + +@end + +@implementation SWGConfiguration + +#pragma mark - Singletion Methods + ++ (instancetype) sharedConfig { + static SWGConfiguration *shardConfig = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + shardConfig = [[self alloc] init]; + }); + return shardConfig; +} + +#pragma mark - Initialize Methods + +- (instancetype) init { + self = [super init]; + if (self) { + self.username = @""; + self.password = @""; + self.mutableApiKey = [NSMutableDictionary dictionary]; + self.mutableApiKeyPrefix = [NSMutableDictionary dictionary]; + } + return self; +} + +#pragma mark - Instance Methods + +- (NSString *) getApiKeyWithPrefix:(NSString *)key { + if ([self.apiKeyPrefix objectForKey:key] && [self.apiKey objectForKey:key]) { + return [NSString stringWithFormat:@"%@ %@", [self.apiKeyPrefix objectForKey:key], [self.apiKey objectForKey:key]]; + } + else if ([self.apiKey objectForKey:key]) { + return [NSString stringWithFormat:@"%@", [self.apiKey objectForKey:key]]; + } + else { + return @""; + } +} + +#pragma mark - Setter Methods + +- (void) setValue:(NSString *)value forApiKeyField:(NSString *)field { + [self.mutableApiKey setValue:value forKey:field]; +} + +- (void) setValue:(NSString *)value forApiKeyPrefixField:(NSString *)field { + [self.mutableApiKeyPrefix setValue:value forKey:field]; +} + +#pragma mark - Getter Methods + +- (NSDictionary *) apiKey { + return [NSDictionary dictionaryWithDictionary:self.mutableApiKey]; +} + +- (NSDictionary *) apiKeyPrefix { + return [NSDictionary dictionaryWithDictionary:self.mutableApiKeyPrefix]; +} + +#pragma mark - + +- (NSDictionary *) authSettings { + return @{ {{#authMethods}}{{#isApiKey}} + @"{{name}}": @{ + @"type": @"api_key", + @"in": {{#isKeyInHeader}}@"header"{{/isKeyInHeader}}{{#isKeyInQuery}}@"query"{{/isKeyInQuery}}, + @"key": @"{{keyParamName}}", + @"value": [self getApiKeyWithPrefix:@"{{keyParamName}}"] + }, + {{/isApiKey}}{{#isBasic}} + @"{{name}}": @{ + @"type": @"basic", + @"in": @"header", + @"key": @"Authorization", + @"value": [self getBasicAuthToken] + }, + {{/isBasic}}{{/authMethods}} + }; +} + +@end diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-header.mustache b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-header.mustache new file mode 100644 index 00000000000..0ddac56acdf --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-header.mustache @@ -0,0 +1,51 @@ +#import + +@interface SWGConfiguration : NSObject + + +/** + * Api key values for Api Key type Authentication + * + * To add or remove api key, use `setValue:forApiKeyField:`. + */ +@property (readonly, nonatomic, strong) NSDictionary *apiKey; + +/** + * Api key prefix values to be prepend to the respective api key + * + * To add or remove prefix, use `setValue:forApiKeyPrefixField:`. + */ +@property (readonly, nonatomic, strong) NSDictionary *apiKeyPrefix; + +/** + * Usename and Password for Basic type Authentication + */ +@property (nonatomic) NSString *username; +@property (nonatomic) NSString *password; + +/** + * Get configuration singleton instance + */ ++ (instancetype) sharedConfig; + +/** + * Sets field in `apiKey` + */ +- (void) setValue:(NSString *)value forApiKeyField:(NSString*)field; + +/** + * Sets field in `apiKeyPrefix` + */ +- (void) setValue:(NSString *)value forApiKeyPrefixField:(NSString *)field; + +/** + * Get API key (with prefix if set) + */ +- (NSString *) getApiKeyWithPrefix:(NSString *) key; + +/** + * Get Authentication Setings + */ +- (NSDictionary *) authSettings; + +@end diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGQueryParamCollection.m b/modules/swagger-codegen/src/main/resources/objc/SWGQueryParamCollection.m index 9ce319940dd..83303045185 100644 --- a/modules/swagger-codegen/src/main/resources/objc/SWGQueryParamCollection.m +++ b/modules/swagger-codegen/src/main/resources/objc/SWGQueryParamCollection.m @@ -13,4 +13,4 @@ return self; } -@end \ No newline at end of file +@end diff --git a/modules/swagger-codegen/src/main/resources/objc/api-body.mustache b/modules/swagger-codegen/src/main/resources/objc/api-body.mustache index abe4376d1ac..40d75bd806b 100644 --- a/modules/swagger-codegen/src/main/resources/objc/api-body.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/api-body.mustache @@ -39,6 +39,8 @@ static NSString * basePath = @"{{basePath}}"; return self; } +#pragma mark - + +({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static {{classname}}* singletonAPI = nil; @@ -129,6 +131,9 @@ static NSString * basePath = @"{{basePath}}"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[{{#consumes}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}]]; + // Authentication setting + NSArray *authSettings = @[{{#authMethods}}@"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}}]; + id bodyDictionary = nil; {{#bodyParam}} id __body = {{paramName}}; diff --git a/modules/swagger-codegen/src/main/resources/objc/api-header.mustache b/modules/swagger-codegen/src/main/resources/objc/api-header.mustache index 4d571f756ce..65f4c39e0b3 100644 --- a/modules/swagger-codegen/src/main/resources/objc/api-header.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/api-header.mustache @@ -10,6 +10,7 @@ @property(nonatomic, assign)SWGApiClient *apiClient; +-(instancetype) initWithApiClient:(SWGApiClient *)apiClient; -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; diff --git a/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache b/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache index 5aabef86841..acaeaf2ddf5 100644 --- a/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache @@ -4,6 +4,7 @@ queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { diff --git a/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache b/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache index 81cf1343e53..da8ea063bfb 100644 --- a/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache @@ -5,6 +5,7 @@ queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { diff --git a/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache b/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache index 3d6b105f227..d44d356526d 100644 --- a/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache @@ -4,6 +4,7 @@ queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { diff --git a/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache b/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache index ab4062a6dbe..7bbbc14c066 100644 --- a/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache @@ -3,6 +3,7 @@ queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/project.pbxproj b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/project.pbxproj index 723caec2cdb..5c1bfabf608 100644 --- a/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/project.pbxproj +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ BA525648922D4C0E9F44D4F1 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 73DA4F1067C343C3962F1542 /* libPods.a */; }; + CF0560EB1B1855CF00C0D4EC /* SWGConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = CF0560EA1B1855CF00C0D4EC /* SWGConfiguration.m */; }; CF31D0991B105E4B00509935 /* SWGApiClientTest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF31D0981B105E4B00509935 /* SWGApiClientTest.m */; }; CFD1B6701B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.m in Sources */ = {isa = PBXBuildFile; fileRef = CFD1B66F1B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.m */; }; CFD1B6711B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.m in Sources */ = {isa = PBXBuildFile; fileRef = CFD1B66F1B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.m */; }; @@ -56,6 +57,8 @@ /* Begin PBXFileReference section */ 73DA4F1067C343C3962F1542 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; A425648B5C0A4849C7668069 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "../Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; + CF0560E91B1855CF00C0D4EC /* SWGConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWGConfiguration.h; sourceTree = ""; }; + CF0560EA1B1855CF00C0D4EC /* SWGConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWGConfiguration.m; sourceTree = ""; }; CF31D0981B105E4B00509935 /* SWGApiClientTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWGApiClientTest.m; sourceTree = ""; }; CFD1B66E1B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JSONValueTransformer+ISO8601.h"; sourceTree = ""; }; CFD1B66F1B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "JSONValueTransformer+ISO8601.m"; sourceTree = ""; }; @@ -234,6 +237,8 @@ EA8B8AA31AC6683700638FBB /* SWGQueryParamCollection.m */, EAEA85CC1811D3AE00F06E69 /* SWGApiClient.h */, EAEA85CD1811D3AE00F06E69 /* SWGApiClient.m */, + CF0560E91B1855CF00C0D4EC /* SWGConfiguration.h */, + CF0560EA1B1855CF00C0D4EC /* SWGConfiguration.m */, EAEA85CE1811D3AE00F06E69 /* SWGCategory.h */, EAEA85CF1811D3AE00F06E69 /* SWGCategory.m */, EAEA85D21811D3AE00F06E69 /* SWGFile.h */, @@ -395,6 +400,7 @@ buildActionMask = 2147483647; files = ( EAEA85E51811D3AE00F06E69 /* SWGCategory.m in Sources */, + CF0560EB1B1855CF00C0D4EC /* SWGConfiguration.m in Sources */, EAEA85ED1811D3AE00F06E69 /* SWGTag.m in Sources */, EA6699B31811D2FA00A70D03 /* ViewController.m in Sources */, EA6699AA1811D2FA00A70D03 /* AppDelegate.m in Sources */, diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/PetstoreClient.xcscheme b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/PetstoreClient.xcscheme new file mode 100644 index 00000000000..1a2a738abea --- /dev/null +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/PetstoreClient.xcscheme @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/xcschememanagement.plist b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 00000000000..912710bdccc --- /dev/null +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,27 @@ + + + + + SchemeUserState + + PetstoreClient.xcscheme + + orderHint + 4 + + + SuppressBuildableAutocreation + + EA6699951811D2FA00A70D03 + + primary + + + EA6699B91811D2FB00A70D03 + + primary + + + + + diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClient/ViewController.m b/samples/client/petstore/objc/PetstoreClient/PetstoreClient/ViewController.m index 7c47bb1f271..d56bc037206 100644 --- a/samples/client/petstore/objc/PetstoreClient/PetstoreClient/ViewController.m +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClient/ViewController.m @@ -8,6 +8,7 @@ #import "ViewController.h" #import "SWGPetApi.h" +#import "SWGConfiguration.h" @interface ViewController () @@ -53,6 +54,14 @@ // } ]; */ + SWGConfiguration *config = [SWGConfiguration sharedConfig]; + config.username = @"foo"; + config.password = @"bar"; + SWGPetApi *api = [[SWGPetApi alloc] init]; + [api addPetWithCompletionBlock:nil + completionHandler:^(NSError *error) { + + }]; } - (void)didReceiveMemoryWarning diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/SWGApiClientTest.m b/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/SWGApiClientTest.m index 0464bf569e9..61925b16960 100644 --- a/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/SWGApiClientTest.m +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/SWGApiClientTest.m @@ -1,16 +1,19 @@ #import #import #import "SWGApiClient.h" +#import "SWGConfiguration.h" @interface SWGApiClientTest : XCTestCase +@property (nonatomic) SWGApiClient *apiClient; + @end @implementation SWGApiClientTest - (void)setUp { [super setUp]; - // Put setup code here. This method is called before the invocation of each test method in the class. + self.apiClient = [[SWGApiClient alloc] init]; } - (void)tearDown { @@ -56,4 +59,43 @@ XCTAssertEqualObjects([SWGApiClient selectHeaderContentType:contentTypes], @"application/json"); } +- (void)testConfiguration { + SWGConfiguration *config = [SWGConfiguration sharedConfig]; + [config setValue:@"123456" forApiKeyField:@"api_key"]; + [config setValue:@"PREFIX" forApiKeyPrefixField:@"api_key"]; + config.username = @"test_username"; + config.password = @"test_password"; + + NSDictionary *headerParams = @{@"test1": @"value1"}; + NSDictionary *queryParams = @{@"test2": @"value2"}; + NSArray *authSettings = @[@"api_key", @"unknown"]; + + // test prefix + XCTAssertEqualObjects(@"PREFIX", config.apiKeyPrefix[@"api_key"]); + [self.apiClient updateHeaderParams:&headerParams + queryParams:&queryParams + WithAuthSettings:authSettings]; + + // test api key auth + XCTAssertEqualObjects(headerParams[@"test1"], @"value1"); + XCTAssertEqualObjects(headerParams[@"api_key"], @"PREFIX 123456"); + XCTAssertEqualObjects(queryParams[@"test2"], @"value2"); + + // test basic auth + XCTAssertEqualObjects(@"test_username", config.username); + XCTAssertEqualObjects(@"test_password", config.password); +} + +- (void)testGetBasicAuthToken { + SWGConfiguration *config = [SWGConfiguration sharedConfig]; + config.username = @"test_username"; + config.password = @"test_password"; + + NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", config.username, config.password]; + NSData *data = [basicAuthCredentials dataUsingEncoding:NSUTF8StringEncoding]; + basicAuthCredentials = [NSString stringWithFormat:@"Basic %@", [data base64EncodedStringWithOptions:0]]; + + XCTAssertEqualObjects(basicAuthCredentials, [config getBasicAuthToken]); +} + @end diff --git a/samples/client/petstore/objc/Podfile.lock b/samples/client/petstore/objc/Podfile.lock index 6ac776ab37a..48b1f809658 100644 --- a/samples/client/petstore/objc/Podfile.lock +++ b/samples/client/petstore/objc/Podfile.lock @@ -20,7 +20,7 @@ PODS: - AFNetworking/UIKit (2.5.4): - AFNetworking/NSURLConnection - AFNetworking/NSURLSession - - ISO8601 (0.2.0) + - ISO8601 (0.3.0) - JSONModel (1.1.0) DEPENDENCIES: @@ -30,7 +30,7 @@ DEPENDENCIES: SPEC CHECKSUMS: AFNetworking: 05edc0ac4c4c8cf57bcf4b84be5b0744b6d8e71e - ISO8601: 962282de75074c38bbfaa7b133b0e743ed6deb8d + ISO8601: 8d8a22d5edf0554a1cf75bac028c76c1dc0ffaef JSONModel: ec77e9865236a7a09d9cf7668df6b4b328d9ec1d COCOAPODS: 0.37.1 diff --git a/samples/client/petstore/objc/client/SWGApiClient.h b/samples/client/petstore/objc/client/SWGApiClient.h index cd6f52db5c6..d1f9203f180 100644 --- a/samples/client/petstore/objc/client/SWGApiClient.h +++ b/samples/client/petstore/objc/client/SWGApiClient.h @@ -54,11 +54,16 @@ extern NSString *const SWGResponseObjectErrorKey; -(void)setHeaderValue:(NSString*) value forKey:(NSString*) forKey; +- (void) updateHeaderParams:(NSDictionary **)headers + queryParams:(NSDictionary **)querys + WithAuthSettings:(NSArray *)authSettings; + -(NSNumber*) dictionary:(NSString*) path method:(NSString*) method queryParams:(NSDictionary*) queryParams body:(id) body headerParams:(NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType:(NSString*) requestContentType responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSDictionary*, NSError *))completionBlock; @@ -68,8 +73,18 @@ extern NSString *const SWGResponseObjectErrorKey; queryParams:(NSDictionary*) queryParams body:(id) body headerParams:(NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType:(NSString*) requestContentType responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSString*, NSError *))completionBlock; @end + + + + + + + + + diff --git a/samples/client/petstore/objc/client/SWGApiClient.m b/samples/client/petstore/objc/client/SWGApiClient.m index b38b02e0e03..5e2985bbe79 100644 --- a/samples/client/petstore/objc/client/SWGApiClient.m +++ b/samples/client/petstore/objc/client/SWGApiClient.m @@ -1,6 +1,7 @@ #import "SWGApiClient.h" #import "SWGFile.h" #import "SWGQueryParamCollection.h" +#import "SWGConfiguration.h" @implementation SWGApiClient @@ -15,10 +16,22 @@ static NSOperationQueue* sharedQueue; static void (^reachabilityChangeBlock)(int); static bool loggingEnabled = true; +#pragma mark - Log Methods + +(void)setLoggingEnabled:(bool) state { loggingEnabled = state; } +- (void)logRequest:(NSURLRequest*)request { + NSLog(@"request: %@", [self descriptionForRequest:request]); +} + +- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error { + NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data ); +} + +#pragma mark - + +(void)clearCache { [[NSURLCache sharedURLCache] removeAllCachedResponses]; } @@ -305,19 +318,47 @@ static bool loggingEnabled = true; return [[request URL] absoluteString]; } -- (void)logRequest:(NSURLRequest*)request { - NSLog(@"request: %@", [self descriptionForRequest:request]); + +/** + * Update header and query params based on authentication settings + */ +- (void) updateHeaderParams:(NSDictionary *__autoreleasing *)headers + queryParams:(NSDictionary *__autoreleasing *)querys + WithAuthSettings:(NSArray *)authSettings { + + if (!authSettings || [authSettings count] == 0) { + return; + } + + NSMutableDictionary *headersWithAuth = [NSMutableDictionary dictionaryWithDictionary:*headers]; + NSMutableDictionary *querysWithAuth = [NSMutableDictionary dictionaryWithDictionary:*querys]; + + SWGConfiguration *config = [SWGConfiguration sharedConfig]; + for (NSString *auth in authSettings) { + NSDictionary *authSetting = [[config authSettings] objectForKey:auth]; + + if (authSetting) { + if ([authSetting[@"in"] isEqualToString:@"header"]) { + [headersWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]]; + } + else if ([authSetting[@"in"] isEqualToString:@"query"]) { + [querysWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]]; + } + } + } + + *headers = [NSDictionary dictionaryWithDictionary:headersWithAuth]; + *querys = [NSDictionary dictionaryWithDictionary:querysWithAuth]; } -- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error { - NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data ); -} +#pragma mark - Perform Request Methods -(NSNumber*) dictionary: (NSString*) path method: (NSString*) method queryParams: (NSDictionary*) queryParams body: (id) body headerParams: (NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType: (NSString*) requestContentType responseContentType: (NSString*) responseContentType completionBlock: (void (^)(NSDictionary*, NSError *))completionBlock { @@ -342,6 +383,9 @@ static bool loggingEnabled = true; else { self.responseSerializer = [AFHTTPResponseSerializer serializer]; } + + // auth setting + [self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings]; NSMutableURLRequest * request = nil; if (body != nil && [body isKindOfClass:[NSArray class]]){ @@ -476,6 +520,7 @@ static bool loggingEnabled = true; queryParams: (NSDictionary*) queryParams body: (id) body headerParams: (NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType: (NSString*) requestContentType responseContentType: (NSString*) responseContentType completionBlock: (void (^)(NSString*, NSError *))completionBlock { @@ -500,6 +545,9 @@ static bool loggingEnabled = true; else { self.responseSerializer = [AFHTTPResponseSerializer serializer]; } + + // auth setting + [self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings]; NSMutableURLRequest * request = nil; if (body != nil && [body isKindOfClass:[NSArray class]]){ diff --git a/samples/client/petstore/objc/client/SWGConfiguration.h b/samples/client/petstore/objc/client/SWGConfiguration.h new file mode 100644 index 00000000000..0ddac56acdf --- /dev/null +++ b/samples/client/petstore/objc/client/SWGConfiguration.h @@ -0,0 +1,51 @@ +#import + +@interface SWGConfiguration : NSObject + + +/** + * Api key values for Api Key type Authentication + * + * To add or remove api key, use `setValue:forApiKeyField:`. + */ +@property (readonly, nonatomic, strong) NSDictionary *apiKey; + +/** + * Api key prefix values to be prepend to the respective api key + * + * To add or remove prefix, use `setValue:forApiKeyPrefixField:`. + */ +@property (readonly, nonatomic, strong) NSDictionary *apiKeyPrefix; + +/** + * Usename and Password for Basic type Authentication + */ +@property (nonatomic) NSString *username; +@property (nonatomic) NSString *password; + +/** + * Get configuration singleton instance + */ ++ (instancetype) sharedConfig; + +/** + * Sets field in `apiKey` + */ +- (void) setValue:(NSString *)value forApiKeyField:(NSString*)field; + +/** + * Sets field in `apiKeyPrefix` + */ +- (void) setValue:(NSString *)value forApiKeyPrefixField:(NSString *)field; + +/** + * Get API key (with prefix if set) + */ +- (NSString *) getApiKeyWithPrefix:(NSString *) key; + +/** + * Get Authentication Setings + */ +- (NSDictionary *) authSettings; + +@end diff --git a/samples/client/petstore/objc/client/SWGConfiguration.m b/samples/client/petstore/objc/client/SWGConfiguration.m new file mode 100644 index 00000000000..f98c5f081de --- /dev/null +++ b/samples/client/petstore/objc/client/SWGConfiguration.m @@ -0,0 +1,91 @@ +#import "SWGConfiguration.h" + +@interface SWGConfiguration () + +@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKey; +@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKeyPrefix; + +@end + +@implementation SWGConfiguration + +#pragma mark - Singletion Methods + ++ (instancetype) sharedConfig { + static SWGConfiguration *shardConfig = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + shardConfig = [[self alloc] init]; + }); + return shardConfig; +} + +#pragma mark - Initialize Methods + +- (instancetype) init { + self = [super init]; + if (self) { + self.username = @""; + self.password = @""; + self.mutableApiKey = [NSMutableDictionary dictionary]; + self.mutableApiKeyPrefix = [NSMutableDictionary dictionary]; + } + return self; +} + +#pragma mark - Instance Methods + +- (NSString *) getApiKeyWithPrefix:(NSString *)key { + if ([self.apiKeyPrefix objectForKey:key] && [self.apiKey objectForKey:key]) { + return [NSString stringWithFormat:@"%@ %@", [self.apiKeyPrefix objectForKey:key], [self.apiKey objectForKey:key]]; + } + else if ([self.apiKey objectForKey:key]) { + return [NSString stringWithFormat:@"%@", [self.apiKey objectForKey:key]]; + } + else { + return @""; + } +} + +#pragma mark - Setter Methods + +- (void) setValue:(NSString *)value forApiKeyField:(NSString *)field { + [self.mutableApiKey setValue:value forKey:field]; +} + +- (void) setValue:(NSString *)value forApiKeyPrefixField:(NSString *)field { + [self.mutableApiKeyPrefix setValue:value forKey:field]; +} + +#pragma mark - Getter Methods + +- (NSDictionary *) apiKey { + return [NSDictionary dictionaryWithDictionary:self.mutableApiKey]; +} + +- (NSDictionary *) apiKeyPrefix { + return [NSDictionary dictionaryWithDictionary:self.mutableApiKeyPrefix]; +} + +#pragma mark - + +- (NSDictionary *) authSettings { + return @{ + @"api_key": @{ + @"type": @"api_key", + @"in": @"header", + @"key": @"api_key", + @"value": [self getApiKeyWithPrefix:@"api_key"] + }, + + @"basic_auth": @{ + @"type": @"basic", + @"in": @"header", + @"key": @"Authorization", + @"value": [self getBasicAuthToken] + }, + + }; +} + +@end diff --git a/samples/client/petstore/objc/client/SWGPetApi.m b/samples/client/petstore/objc/client/SWGPetApi.m index 9487713984b..0b2c059fb3b 100644 --- a/samples/client/petstore/objc/client/SWGPetApi.m +++ b/samples/client/petstore/objc/client/SWGPetApi.m @@ -38,6 +38,8 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; return self; } +#pragma mark - + +(SWGPetApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static SWGPetApi* singletonAPI = nil; @@ -115,6 +117,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[@"application/json", @"application/xml"]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; id __body = body; @@ -160,6 +165,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -218,6 +224,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[@"application/json", @"application/xml"]]; + // Authentication setting + NSArray *authSettings = @[@"basic_auth"]; + id bodyDictionary = nil; id __body = body; @@ -263,6 +272,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -327,6 +337,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; @@ -346,6 +359,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -427,6 +441,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; @@ -446,6 +463,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -525,6 +543,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[@"api_key", @"petstore_auth"]; + id bodyDictionary = nil; @@ -552,6 +573,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -627,6 +649,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[@"application/x-www-form-urlencoded"]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; @@ -665,6 +690,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -731,6 +757,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; @@ -753,6 +782,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -819,6 +849,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[@"multipart/form-data"]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; @@ -864,6 +897,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { diff --git a/samples/client/petstore/objc/client/SWGQueryParamCollection.m b/samples/client/petstore/objc/client/SWGQueryParamCollection.m index 9ce319940dd..83303045185 100644 --- a/samples/client/petstore/objc/client/SWGQueryParamCollection.m +++ b/samples/client/petstore/objc/client/SWGQueryParamCollection.m @@ -13,4 +13,4 @@ return self; } -@end \ No newline at end of file +@end diff --git a/samples/client/petstore/objc/client/SWGStoreApi.h b/samples/client/petstore/objc/client/SWGStoreApi.h index c2d0dd6b36b..49d8db806c8 100644 --- a/samples/client/petstore/objc/client/SWGStoreApi.h +++ b/samples/client/petstore/objc/client/SWGStoreApi.h @@ -8,6 +8,7 @@ @property(nonatomic, assign)SWGApiClient *apiClient; +-(instancetype) initWithApiClient:(SWGApiClient *)apiClient; -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +(SWGStoreApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; diff --git a/samples/client/petstore/objc/client/SWGStoreApi.m b/samples/client/petstore/objc/client/SWGStoreApi.m index 98b9d9a4eec..a112db6d639 100644 --- a/samples/client/petstore/objc/client/SWGStoreApi.m +++ b/samples/client/petstore/objc/client/SWGStoreApi.m @@ -37,6 +37,8 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; return self; } +#pragma mark - + +(SWGStoreApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static SWGStoreApi* singletonAPI = nil; @@ -112,6 +114,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[@"api_key"]; + id bodyDictionary = nil; @@ -131,6 +136,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -199,6 +205,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; id __body = body; @@ -249,6 +258,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -320,6 +330,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -347,6 +360,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -418,6 +432,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -440,6 +457,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { diff --git a/samples/client/petstore/objc/client/SWGUserApi.h b/samples/client/petstore/objc/client/SWGUserApi.h index d9d5a8abc18..e6e73ddfba6 100644 --- a/samples/client/petstore/objc/client/SWGUserApi.h +++ b/samples/client/petstore/objc/client/SWGUserApi.h @@ -8,6 +8,7 @@ @property(nonatomic, assign)SWGApiClient *apiClient; +-(instancetype) initWithApiClient:(SWGApiClient *)apiClient; -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +(SWGUserApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; diff --git a/samples/client/petstore/objc/client/SWGUserApi.m b/samples/client/petstore/objc/client/SWGUserApi.m index 97a79f01b6d..e2fe69aca8d 100644 --- a/samples/client/petstore/objc/client/SWGUserApi.m +++ b/samples/client/petstore/objc/client/SWGUserApi.m @@ -37,6 +37,8 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; return self; } +#pragma mark - + +(SWGUserApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static SWGUserApi* singletonAPI = nil; @@ -114,6 +116,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; id __body = body; @@ -159,6 +164,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -217,6 +223,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; id __body = body; @@ -262,6 +271,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -320,6 +330,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; id __body = body; @@ -365,6 +378,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -433,6 +447,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -457,6 +474,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -524,6 +542,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -546,6 +567,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -608,6 +630,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -635,6 +660,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -708,6 +734,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; id __body = body; @@ -753,6 +782,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -815,6 +845,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -837,6 +870,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { From 83d069d05341c9136221b340cf958a9ce54a8745 Mon Sep 17 00:00:00 2001 From: wing328 Date: Sun, 31 May 2015 09:49:24 +0800 Subject: [PATCH 48/72] add support for obj, remove null from serialized json string --- .../codegen/languages/PhpClientCodegen.java | 1 + .../src/main/resources/php/APIClient.mustache | 6 +++-- .../php/SwaggerClient-php/lib/APIClient.php | 4 +++- samples/client/petstore/php/test.php | 24 +++++++++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java index 55d358154f8..9d29baffbe2 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java @@ -82,6 +82,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("map", "map"); typeMapping.put("array", "array"); typeMapping.put("list", "array"); + typeMapping.put("object", "object"); supportingFiles.add(new SupportingFile("composer.mustache", packagePath, "composer.json")); supportingFiles.add(new SupportingFile("configuration.mustache", packagePath + "/lib", "Configuration.php")); diff --git a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache index 70717056b9e..9d360b6482a 100644 --- a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache @@ -278,7 +278,9 @@ class APIClient { } else if (is_object($data)) { $values = array(); foreach (array_keys($data::$swaggerTypes) as $property) { - $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); + if ($data->$property !== null) { + $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); + } } $sanitized = $values; } else { @@ -383,7 +385,7 @@ class APIClient { $deserialized = $values; } elseif ($class == 'DateTime') { $deserialized = new \DateTime($data); - } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool'))) { + } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { settype($data, $class); $deserialized = $data; } else { diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php index f7002fba18d..44766040a7a 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php @@ -283,7 +283,9 @@ class APIClient { } else if (is_object($data)) { $values = array(); foreach (array_keys($data::$swaggerTypes) as $property) { - $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); + if ($data->$property !== null) { + $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); + } } $sanitized = $values; } else { diff --git a/samples/client/petstore/php/test.php b/samples/client/petstore/php/test.php index 41c206ee6b0..78f8b225665 100644 --- a/samples/client/petstore/php/test.php +++ b/samples/client/petstore/php/test.php @@ -8,13 +8,37 @@ require_once('SwaggerClient-php/SwaggerClient.php'); $petId = 10005; // ID of pet that needs to be fetched try { + // get pet by id //$pet_api = new SwaggerClient\PetAPI($api_client); $pet_api = new SwaggerClient\PetAPI(); // return Pet (model) $response = $pet_api->getPetById($petId); var_dump($response); + + // add pet (post json) + $new_pet_id = 10005; + $new_pet = new SwaggerClient\models\Pet; + $new_pet->id = $new_pet_id; + $new_pet->name = "PHP Unit Test"; + // new tag + $tag= new SwaggerClient\models\Tag; + $tag->id = $new_pet_id; // use the same id as pet + //$tag->name = "test php tag"; + // new category + $category = new SwaggerClient\models\Category; + $category->id = 0; // use the same id as pet + //$category->name = "test php category"; + + $new_pet->tags = array($tag); + $new_pet->category = $category; + + $pet_api = new SwaggerClient\PetAPI(); + // add a new pet (model) + $add_response = $pet_api->addPet($new_pet); + } catch (Exception $e) { echo 'Caught exception: ', $e->getMessage(), "\n"; } + ?> From 8d708c2442b7f1c3760cde84a85acfe4f2e35daf Mon Sep 17 00:00:00 2001 From: wing328 Date: Sun, 31 May 2015 11:17:59 +0800 Subject: [PATCH 49/72] add test case for default header --- .../src/main/resources/php/APIClient.mustache | 2 +- .../petstore/php/SwaggerClient-php/lib/APIClient.php | 11 ++++------- samples/client/petstore/php/test.php | 4 ++++ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache index 9d360b6482a..aa85a2b1a37 100644 --- a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache @@ -182,7 +182,7 @@ class APIClient { $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); # construct the http header - if ($headerParams != null) { + if ($headerParams !== null) { # add default header $headerParams = array_merge((array)self::$default_header, $headerParams); diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php index 44766040a7a..de75c7252e1 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php @@ -187,13 +187,10 @@ class APIClient { $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); # construct the http header - if ($headerParams != null) { - # add default header - $headerParams = array_merge((array)self::$default_header, $headerParams); + $headerParams = array_merge((array)self::$default_header, (array)$headerParams); - foreach ($headerParams as $key => $val) { - $headers[] = "$key: $val"; - } + foreach ($headerParams as $key => $val) { + $headers[] = "$key: $val"; } // form data @@ -390,7 +387,7 @@ class APIClient { $deserialized = $values; } elseif ($class == 'DateTime') { $deserialized = new \DateTime($data); - } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool'))) { + } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { settype($data, $class); $deserialized = $data; } else { diff --git a/samples/client/petstore/php/test.php b/samples/client/petstore/php/test.php index 78f8b225665..7bc755f72e6 100644 --- a/samples/client/petstore/php/test.php +++ b/samples/client/petstore/php/test.php @@ -2,6 +2,8 @@ //require_once('vendor/autoload.php'); require_once('SwaggerClient-php/SwaggerClient.php'); +$c = array_merge((array)$a, (array)$b); + // initialize the API client //$api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); //$api_client->addDefaultHeader("test1", "value1"); @@ -11,6 +13,8 @@ try { // get pet by id //$pet_api = new SwaggerClient\PetAPI($api_client); $pet_api = new SwaggerClient\PetAPI(); + // test default header + $pet_api->getApiClient()->addDefaultHeader("TEST_API_KEY", "09182sdkanafndsl903"); // return Pet (model) $response = $pet_api->getPetById($petId); var_dump($response); From f357f4c9d75fae5ebf40729b9bfdb74e80733e9b Mon Sep 17 00:00:00 2001 From: wing328 Date: Mon, 1 Jun 2015 14:24:09 +0800 Subject: [PATCH 50/72] fix default header --- .../src/main/resources/php/APIClient.mustache | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache index aa85a2b1a37..cbde8987da9 100644 --- a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache @@ -182,13 +182,10 @@ class APIClient { $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); # construct the http header - if ($headerParams !== null) { - # add default header - $headerParams = array_merge((array)self::$default_header, $headerParams); + $headerParams = array_merge((array)self::$default_header, (array)$headerParams); - foreach ($headerParams as $key => $val) { - $headers[] = "$key: $val"; - } + foreach ($headerParams as $key => $val) { + $headers[] = "$key: $val"; } // form data From 762a3279ea68a6124073112b2ff5b840524e41de Mon Sep 17 00:00:00 2001 From: wing328 Date: Mon, 1 Jun 2015 14:50:57 +0800 Subject: [PATCH 51/72] clean up test.php --- samples/client/petstore/php/test.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/samples/client/petstore/php/test.php b/samples/client/petstore/php/test.php index 7bc755f72e6..de5f4ba3f12 100644 --- a/samples/client/petstore/php/test.php +++ b/samples/client/petstore/php/test.php @@ -2,8 +2,6 @@ //require_once('vendor/autoload.php'); require_once('SwaggerClient-php/SwaggerClient.php'); -$c = array_merge((array)$a, (array)$b); - // initialize the API client //$api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); //$api_client->addDefaultHeader("test1", "value1"); From 3e0913a813bc0e9d6d55c32ad72e41da4986a916 Mon Sep 17 00:00:00 2001 From: hrachya Date: Mon, 1 Jun 2015 10:43:23 -0700 Subject: [PATCH 52/72] removing generic header comments --- .../java/com/wordnik/swagger/codegen/cmd/ConfigHelp.java | 5 ----- .../src/main/java/com/wordnik/swagger/codegen/CliOption.java | 5 ----- modules/swagger-codegen/src/main/java/config/Config.java | 5 ----- .../swagger-codegen/src/main/java/config/ConfigParser.java | 5 ----- 4 files changed, 20 deletions(-) diff --git a/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/ConfigHelp.java b/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/ConfigHelp.java index 6934bcf702e..fbdca12e6e8 100644 --- a/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/ConfigHelp.java +++ b/modules/swagger-codegen-cli/src/main/java/com/wordnik/swagger/codegen/cmd/ConfigHelp.java @@ -1,8 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package com.wordnik.swagger.codegen.cmd; import com.wordnik.swagger.codegen.CliOption; diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java index 4294d097116..8ea0b60db26 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/CliOption.java @@ -1,8 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package com.wordnik.swagger.codegen; public class CliOption { diff --git a/modules/swagger-codegen/src/main/java/config/Config.java b/modules/swagger-codegen/src/main/java/config/Config.java index 745824bd816..9bc4bf58624 100644 --- a/modules/swagger-codegen/src/main/java/config/Config.java +++ b/modules/swagger-codegen/src/main/java/config/Config.java @@ -1,8 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package config; import com.google.common.collect.ImmutableMap; diff --git a/modules/swagger-codegen/src/main/java/config/ConfigParser.java b/modules/swagger-codegen/src/main/java/config/ConfigParser.java index 019061faa33..cbb1b78f645 100644 --- a/modules/swagger-codegen/src/main/java/config/ConfigParser.java +++ b/modules/swagger-codegen/src/main/java/config/ConfigParser.java @@ -1,8 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package config; import com.fasterxml.jackson.databind.JsonNode; From 86971ee752842bee8dba1bd5965e92168c690783 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 2 Jun 2015 11:50:47 +0800 Subject: [PATCH 53/72] added comments for objc client --- .../src/main/resources/objc/SWGApiClient.h | 77 ++++++++++++++++--- .../petstore/objc/client/SWGApiClient.h | 77 ++++++++++++++++--- .../petstore/objc/client/SWGConfiguration.m | 7 -- .../client/petstore/objc/client/SWGPetApi.m | 2 +- 4 files changed, 133 insertions(+), 30 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h index d1f9203f180..fa48aa70965 100644 --- a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h +++ b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h @@ -3,7 +3,7 @@ /** * A key for `NSError` user info dictionaries. - * + * * The corresponding value is the parsed response body for an HTTP error. */ extern NSString *const SWGResponseObjectErrorKey; @@ -20,44 +20,104 @@ extern NSString *const SWGResponseObjectErrorKey; @property(nonatomic, assign) BOOL logHTTP; @property(nonatomic, readonly) NSOperationQueue* queue; +/** + * Get the Api Client instance from pool + */ +(SWGApiClient *)sharedClientFromPool:(NSString *)baseUrl; +/** + * Get the operations queue + */ +(NSOperationQueue*) sharedQueue; +/** + * Turn on logging + */ +(void)setLoggingEnabled:(bool) state; +/** + * Clear Cache + */ +(void)clearCache; +/** + * Turn on cache + */ +(void)setCacheEnabled:(BOOL) enabled; +/** + * Get the request queue size + */ +(unsigned long)requestQueueSize; +/** + * Set the client unreachable + */ +(void) setOfflineState:(BOOL) state; +/** + * Get the client reachability + */ +(AFNetworkReachabilityStatus) getReachabilityStatus; +/** + * Get the next request id + */ +(NSNumber*) nextRequestId; +/** + * Generate request id and add it to the queue + */ +(NSNumber*) queueRequest; +/** + * Remove request id from the queue + */ +(void) cancelRequest:(NSNumber*)requestId; +/** + * URL encode NSString + */ +(NSString*) escape:(id)unescaped; +/** + * Set the client reachability + */ +(void) setReachabilityChangeBlock:(void(^)(int))changeBlock; +/** + * Set the client reachability strategy + */ +(void) configureCacheReachibilityForHost:(NSString*)host; +/** + * Detect Accept header from accepts NSArray + */ +(NSString *) selectHeaderAccept:(NSArray *)accepts; + +/** + * Detect Content-Type header from contentTypes NSArray + */ +(NSString *) selectHeaderContentType:(NSArray *)contentTypes; +/** + * Set header for request + */ -(void)setHeaderValue:(NSString*) value forKey:(NSString*) forKey; +/** + * Update header parameters and query parameters for authentication + */ - (void) updateHeaderParams:(NSDictionary **)headers queryParams:(NSDictionary **)querys WithAuthSettings:(NSArray *)authSettings; +/** + * Perform request + * + * @discussion Request with non-empty response + */ -(NSNumber*) dictionary:(NSString*) path method:(NSString*) method queryParams:(NSDictionary*) queryParams @@ -68,6 +128,11 @@ extern NSString *const SWGResponseObjectErrorKey; responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSDictionary*, NSError *))completionBlock; +/** + * Perform request + * + * @discussion Request with empty response + */ -(NSNumber*) stringWithCompletionBlock:(NSString*) path method:(NSString*) method queryParams:(NSDictionary*) queryParams @@ -78,13 +143,3 @@ extern NSString *const SWGResponseObjectErrorKey; responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSString*, NSError *))completionBlock; @end - - - - - - - - - - diff --git a/samples/client/petstore/objc/client/SWGApiClient.h b/samples/client/petstore/objc/client/SWGApiClient.h index d1f9203f180..fa48aa70965 100644 --- a/samples/client/petstore/objc/client/SWGApiClient.h +++ b/samples/client/petstore/objc/client/SWGApiClient.h @@ -3,7 +3,7 @@ /** * A key for `NSError` user info dictionaries. - * + * * The corresponding value is the parsed response body for an HTTP error. */ extern NSString *const SWGResponseObjectErrorKey; @@ -20,44 +20,104 @@ extern NSString *const SWGResponseObjectErrorKey; @property(nonatomic, assign) BOOL logHTTP; @property(nonatomic, readonly) NSOperationQueue* queue; +/** + * Get the Api Client instance from pool + */ +(SWGApiClient *)sharedClientFromPool:(NSString *)baseUrl; +/** + * Get the operations queue + */ +(NSOperationQueue*) sharedQueue; +/** + * Turn on logging + */ +(void)setLoggingEnabled:(bool) state; +/** + * Clear Cache + */ +(void)clearCache; +/** + * Turn on cache + */ +(void)setCacheEnabled:(BOOL) enabled; +/** + * Get the request queue size + */ +(unsigned long)requestQueueSize; +/** + * Set the client unreachable + */ +(void) setOfflineState:(BOOL) state; +/** + * Get the client reachability + */ +(AFNetworkReachabilityStatus) getReachabilityStatus; +/** + * Get the next request id + */ +(NSNumber*) nextRequestId; +/** + * Generate request id and add it to the queue + */ +(NSNumber*) queueRequest; +/** + * Remove request id from the queue + */ +(void) cancelRequest:(NSNumber*)requestId; +/** + * URL encode NSString + */ +(NSString*) escape:(id)unescaped; +/** + * Set the client reachability + */ +(void) setReachabilityChangeBlock:(void(^)(int))changeBlock; +/** + * Set the client reachability strategy + */ +(void) configureCacheReachibilityForHost:(NSString*)host; +/** + * Detect Accept header from accepts NSArray + */ +(NSString *) selectHeaderAccept:(NSArray *)accepts; + +/** + * Detect Content-Type header from contentTypes NSArray + */ +(NSString *) selectHeaderContentType:(NSArray *)contentTypes; +/** + * Set header for request + */ -(void)setHeaderValue:(NSString*) value forKey:(NSString*) forKey; +/** + * Update header parameters and query parameters for authentication + */ - (void) updateHeaderParams:(NSDictionary **)headers queryParams:(NSDictionary **)querys WithAuthSettings:(NSArray *)authSettings; +/** + * Perform request + * + * @discussion Request with non-empty response + */ -(NSNumber*) dictionary:(NSString*) path method:(NSString*) method queryParams:(NSDictionary*) queryParams @@ -68,6 +128,11 @@ extern NSString *const SWGResponseObjectErrorKey; responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSDictionary*, NSError *))completionBlock; +/** + * Perform request + * + * @discussion Request with empty response + */ -(NSNumber*) stringWithCompletionBlock:(NSString*) path method:(NSString*) method queryParams:(NSDictionary*) queryParams @@ -78,13 +143,3 @@ extern NSString *const SWGResponseObjectErrorKey; responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSString*, NSError *))completionBlock; @end - - - - - - - - - - diff --git a/samples/client/petstore/objc/client/SWGConfiguration.m b/samples/client/petstore/objc/client/SWGConfiguration.m index f98c5f081de..0c477edbfc5 100644 --- a/samples/client/petstore/objc/client/SWGConfiguration.m +++ b/samples/client/petstore/objc/client/SWGConfiguration.m @@ -78,13 +78,6 @@ @"value": [self getApiKeyWithPrefix:@"api_key"] }, - @"basic_auth": @{ - @"type": @"basic", - @"in": @"header", - @"key": @"Authorization", - @"value": [self getBasicAuthToken] - }, - }; } diff --git a/samples/client/petstore/objc/client/SWGPetApi.m b/samples/client/petstore/objc/client/SWGPetApi.m index 0b2c059fb3b..c14da125af5 100644 --- a/samples/client/petstore/objc/client/SWGPetApi.m +++ b/samples/client/petstore/objc/client/SWGPetApi.m @@ -225,7 +225,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[@"application/json", @"application/xml"]]; // Authentication setting - NSArray *authSettings = @[@"basic_auth"]; + NSArray *authSettings = @[@"petstore_auth"]; id bodyDictionary = nil; From 699df0029be55ef354437a1766b7f40d2321109d Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 2 Jun 2015 15:33:33 +0800 Subject: [PATCH 54/72] updated comments for objc client. --- .../src/main/resources/objc/SWGApiClient.h | 79 ++++++++++++++++++- .../objc/SWGConfiguration-body.mustache | 8 ++ .../objc/SWGConfiguration-header.mustache | 5 ++ .../petstore/objc/client/SWGApiClient.h | 79 ++++++++++++++++++- .../petstore/objc/client/SWGConfiguration.h | 5 ++ .../petstore/objc/client/SWGConfiguration.m | 8 ++ 6 files changed, 176 insertions(+), 8 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h index fa48aa70965..250811c4016 100644 --- a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h +++ b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h @@ -22,16 +22,24 @@ extern NSString *const SWGResponseObjectErrorKey; /** * Get the Api Client instance from pool + * + * @param baseUrl The base url of api client. + * + * @return The SWGApiClient instance. */ +(SWGApiClient *)sharedClientFromPool:(NSString *)baseUrl; /** * Get the operations queue + * + * @return The `shardQueue` static variable. */ +(NSOperationQueue*) sharedQueue; /** * Turn on logging + * + * @param state logging state, must be `YES` or `NO` */ +(void)setLoggingEnabled:(bool) state; @@ -42,72 +50,109 @@ extern NSString *const SWGResponseObjectErrorKey; /** * Turn on cache + * + * @param enabled If the cached is enable, must be `YES` or `NO` */ +(void)setCacheEnabled:(BOOL) enabled; /** * Get the request queue size + * + * @return The size of `queuedRequests` static variable. */ +(unsigned long)requestQueueSize; /** * Set the client unreachable + * + * @param state off line state, must be `YES` or `NO` */ +(void) setOfflineState:(BOOL) state; /** * Get the client reachability + * + * @return The client reachability. */ +(AFNetworkReachabilityStatus) getReachabilityStatus; /** * Get the next request id + * + * @return The next executed request id. */ +(NSNumber*) nextRequestId; /** * Generate request id and add it to the queue + * + * @return The next executed request id. */ +(NSNumber*) queueRequest; /** * Remove request id from the queue + * + * @param requestId The request which will be removed. */ +(void) cancelRequest:(NSNumber*)requestId; /** * URL encode NSString + * + * @param unescaped The string which will be escaped. + * + * @return The escaped string. */ +(NSString*) escape:(id)unescaped; /** - * Set the client reachability + * Customize the behavior when the reachability changed + * + * @param changeBlock The block will be executed when the reachability changed. */ +(void) setReachabilityChangeBlock:(void(^)(int))changeBlock; /** * Set the client reachability strategy + * + * @param host The host of SWGApiClient. */ +(void) configureCacheReachibilityForHost:(NSString*)host; /** * Detect Accept header from accepts NSArray + * + * @param accepts NSArray of header + * + * @return The Accept header */ +(NSString *) selectHeaderAccept:(NSArray *)accepts; /** * Detect Content-Type header from contentTypes NSArray + * + * @param contentTypes NSArray of header + * + * @return The Content-Type header */ +(NSString *) selectHeaderContentType:(NSArray *)contentTypes; /** * Set header for request + * + * @param value The header value + * @param forKey The header key */ -(void)setHeaderValue:(NSString*) value - forKey:(NSString*) forKey; + forKey:(NSString*) forKey; /** * Update header parameters and query parameters for authentication + * + * @param headers The header parameter will be udpated, passed by pointer to pointer. + * @param querys The query parameters will be updated, passed by pointer to pointer. + * @param authSettings The authentication names NSArray. */ - (void) updateHeaderParams:(NSDictionary **)headers queryParams:(NSDictionary **)querys @@ -116,7 +161,19 @@ extern NSString *const SWGResponseObjectErrorKey; /** * Perform request * - * @discussion Request with non-empty response + * Request with non-empty response + * + * @param path Request url. + * @param method Request method. + * @param queryParams Request query parameters. + * @param body Request body. + * @param headerParams Request header parameters. + * @param authSettings Request authentication names. + * @param requestContentType Request content-type. + * @param responseContentType Response content-type. + * @param completionBlock The block will be executed when the request completed. + * + * @return The request id. */ -(NSNumber*) dictionary:(NSString*) path method:(NSString*) method @@ -131,7 +188,19 @@ extern NSString *const SWGResponseObjectErrorKey; /** * Perform request * - * @discussion Request with empty response + * Request with empty response + * + * @param path Request url. + * @param method Request method. + * @param queryParams Request query parameters. + * @param body Request body. + * @param headerParams Request header parameters. + * @param authSettings Request authentication names. + * @param requestContentType Request content-type. + * @param responseContentType Response content-type. + * @param completionBlock The block will be executed when the request completed. + * + * @return The request id. */ -(NSNumber*) stringWithCompletionBlock:(NSString*) path method:(NSString*) method @@ -143,3 +212,5 @@ extern NSString *const SWGResponseObjectErrorKey; responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSString*, NSError *))completionBlock; @end + + diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-body.mustache b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-body.mustache index b326244fe0a..1e5e7135574 100644 --- a/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-body.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-body.mustache @@ -47,6 +47,14 @@ } } +- (NSString *) getBasicAuthToken { + NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", self.username, self.password]; + NSData *data = [basicAuthCredentials dataUsingEncoding:NSUTF8StringEncoding]; + basicAuthCredentials = [NSString stringWithFormat:@"Basic %@", [data base64EncodedStringWithOptions:0]]; + + return basicAuthCredentials; +} + #pragma mark - Setter Methods - (void) setValue:(NSString *)value forApiKeyField:(NSString *)field { diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-header.mustache b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-header.mustache index 0ddac56acdf..33023ca3c6f 100644 --- a/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-header.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-header.mustache @@ -43,6 +43,11 @@ */ - (NSString *) getApiKeyWithPrefix:(NSString *) key; +/** + * Get Basic Auth token + */ +- (NSString *) getBasicAuthToken; + /** * Get Authentication Setings */ diff --git a/samples/client/petstore/objc/client/SWGApiClient.h b/samples/client/petstore/objc/client/SWGApiClient.h index fa48aa70965..250811c4016 100644 --- a/samples/client/petstore/objc/client/SWGApiClient.h +++ b/samples/client/petstore/objc/client/SWGApiClient.h @@ -22,16 +22,24 @@ extern NSString *const SWGResponseObjectErrorKey; /** * Get the Api Client instance from pool + * + * @param baseUrl The base url of api client. + * + * @return The SWGApiClient instance. */ +(SWGApiClient *)sharedClientFromPool:(NSString *)baseUrl; /** * Get the operations queue + * + * @return The `shardQueue` static variable. */ +(NSOperationQueue*) sharedQueue; /** * Turn on logging + * + * @param state logging state, must be `YES` or `NO` */ +(void)setLoggingEnabled:(bool) state; @@ -42,72 +50,109 @@ extern NSString *const SWGResponseObjectErrorKey; /** * Turn on cache + * + * @param enabled If the cached is enable, must be `YES` or `NO` */ +(void)setCacheEnabled:(BOOL) enabled; /** * Get the request queue size + * + * @return The size of `queuedRequests` static variable. */ +(unsigned long)requestQueueSize; /** * Set the client unreachable + * + * @param state off line state, must be `YES` or `NO` */ +(void) setOfflineState:(BOOL) state; /** * Get the client reachability + * + * @return The client reachability. */ +(AFNetworkReachabilityStatus) getReachabilityStatus; /** * Get the next request id + * + * @return The next executed request id. */ +(NSNumber*) nextRequestId; /** * Generate request id and add it to the queue + * + * @return The next executed request id. */ +(NSNumber*) queueRequest; /** * Remove request id from the queue + * + * @param requestId The request which will be removed. */ +(void) cancelRequest:(NSNumber*)requestId; /** * URL encode NSString + * + * @param unescaped The string which will be escaped. + * + * @return The escaped string. */ +(NSString*) escape:(id)unescaped; /** - * Set the client reachability + * Customize the behavior when the reachability changed + * + * @param changeBlock The block will be executed when the reachability changed. */ +(void) setReachabilityChangeBlock:(void(^)(int))changeBlock; /** * Set the client reachability strategy + * + * @param host The host of SWGApiClient. */ +(void) configureCacheReachibilityForHost:(NSString*)host; /** * Detect Accept header from accepts NSArray + * + * @param accepts NSArray of header + * + * @return The Accept header */ +(NSString *) selectHeaderAccept:(NSArray *)accepts; /** * Detect Content-Type header from contentTypes NSArray + * + * @param contentTypes NSArray of header + * + * @return The Content-Type header */ +(NSString *) selectHeaderContentType:(NSArray *)contentTypes; /** * Set header for request + * + * @param value The header value + * @param forKey The header key */ -(void)setHeaderValue:(NSString*) value - forKey:(NSString*) forKey; + forKey:(NSString*) forKey; /** * Update header parameters and query parameters for authentication + * + * @param headers The header parameter will be udpated, passed by pointer to pointer. + * @param querys The query parameters will be updated, passed by pointer to pointer. + * @param authSettings The authentication names NSArray. */ - (void) updateHeaderParams:(NSDictionary **)headers queryParams:(NSDictionary **)querys @@ -116,7 +161,19 @@ extern NSString *const SWGResponseObjectErrorKey; /** * Perform request * - * @discussion Request with non-empty response + * Request with non-empty response + * + * @param path Request url. + * @param method Request method. + * @param queryParams Request query parameters. + * @param body Request body. + * @param headerParams Request header parameters. + * @param authSettings Request authentication names. + * @param requestContentType Request content-type. + * @param responseContentType Response content-type. + * @param completionBlock The block will be executed when the request completed. + * + * @return The request id. */ -(NSNumber*) dictionary:(NSString*) path method:(NSString*) method @@ -131,7 +188,19 @@ extern NSString *const SWGResponseObjectErrorKey; /** * Perform request * - * @discussion Request with empty response + * Request with empty response + * + * @param path Request url. + * @param method Request method. + * @param queryParams Request query parameters. + * @param body Request body. + * @param headerParams Request header parameters. + * @param authSettings Request authentication names. + * @param requestContentType Request content-type. + * @param responseContentType Response content-type. + * @param completionBlock The block will be executed when the request completed. + * + * @return The request id. */ -(NSNumber*) stringWithCompletionBlock:(NSString*) path method:(NSString*) method @@ -143,3 +212,5 @@ extern NSString *const SWGResponseObjectErrorKey; responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSString*, NSError *))completionBlock; @end + + diff --git a/samples/client/petstore/objc/client/SWGConfiguration.h b/samples/client/petstore/objc/client/SWGConfiguration.h index 0ddac56acdf..33023ca3c6f 100644 --- a/samples/client/petstore/objc/client/SWGConfiguration.h +++ b/samples/client/petstore/objc/client/SWGConfiguration.h @@ -43,6 +43,11 @@ */ - (NSString *) getApiKeyWithPrefix:(NSString *) key; +/** + * Get Basic Auth token + */ +- (NSString *) getBasicAuthToken; + /** * Get Authentication Setings */ diff --git a/samples/client/petstore/objc/client/SWGConfiguration.m b/samples/client/petstore/objc/client/SWGConfiguration.m index 0c477edbfc5..89d5a597946 100644 --- a/samples/client/petstore/objc/client/SWGConfiguration.m +++ b/samples/client/petstore/objc/client/SWGConfiguration.m @@ -47,6 +47,14 @@ } } +- (NSString *) getBasicAuthToken { + NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", self.username, self.password]; + NSData *data = [basicAuthCredentials dataUsingEncoding:NSUTF8StringEncoding]; + basicAuthCredentials = [NSString stringWithFormat:@"Basic %@", [data base64EncodedStringWithOptions:0]]; + + return basicAuthCredentials; +} + #pragma mark - Setter Methods - (void) setValue:(NSString *)value forApiKeyField:(NSString *)field { From 19540ed7f004a3c8fae71ed7d8313e30e787a655 Mon Sep 17 00:00:00 2001 From: xhh Date: Tue, 2 Jun 2015 15:33:44 +0800 Subject: [PATCH 55/72] Store response headers and body in ApiException --- .../main/resources/Java/ApiClient.mustache | 10 +++-- .../main/resources/Java/apiException.mustache | 40 ++++++++++++++++--- .../java/io/swagger/client/ApiClient.java | 10 +++-- .../java/io/swagger/client/ApiException.java | 40 ++++++++++++++++--- 4 files changed, 82 insertions(+), 18 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache index 239ce54a34a..45987bded75 100644 --- a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache @@ -157,7 +157,7 @@ public class ApiClient { } } catch (IOException e) { - throw new ApiException(500, e.getMessage()); + throw new ApiException(500, e.getMessage(), null, json); } } @@ -260,9 +260,11 @@ public class ApiClient { } else { String message = "error"; + String respBody = null; if(response.hasEntity()) { try{ - message = String.valueOf(response.getEntity(String.class)); + respBody = String.valueOf(response.getEntity(String.class)); + message = respBody; } catch (RuntimeException e) { // e.printStackTrace(); @@ -270,7 +272,9 @@ public class ApiClient { } throw new ApiException( response.getClientResponseStatus().getStatusCode(), - message); + message, + response.getHeaders(), + respBody); } } diff --git a/modules/swagger-codegen/src/main/resources/Java/apiException.mustache b/modules/swagger-codegen/src/main/resources/Java/apiException.mustache index a6bcba75b7c..aac7caaf019 100644 --- a/modules/swagger-codegen/src/main/resources/Java/apiException.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/apiException.mustache @@ -1,8 +1,13 @@ package {{invokerPackage}}; +import java.util.Map; +import java.util.List; + public class ApiException extends Exception { - int code = 0; - String message = null; + private int code = 0; + private String message = null; + private Map> responseHeaders = null; + private String responseBody = null; public ApiException() {} @@ -11,19 +16,42 @@ public class ApiException extends Exception { this.message = message; } + public ApiException(int code, String message, Map> responseHeaders, String responseBody) { + this.code = code; + this.message = message; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + public int getCode() { return code; } - + public void setCode(int code) { this.code = code; } - + public String getMessage() { return message; } - + public void setMessage(String message) { this.message = message; } -} \ No newline at end of file + + public Map> getResponseHeaders() { + return responseHeaders; + } + + public void setResponseHeaders(Map> responseHeaders) { + this.responseHeaders = responseHeaders; + } + + public String getResponseBody() { + return responseBody; + } + + public void setResponseBody(String responseBody) { + this.responseBody = responseBody; + } +} diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java index ec0a150ef4e..6a4dfffefab 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java @@ -157,7 +157,7 @@ public class ApiClient { } } catch (IOException e) { - throw new ApiException(500, e.getMessage()); + throw new ApiException(500, e.getMessage(), null, json); } } @@ -260,9 +260,11 @@ public class ApiClient { } else { String message = "error"; + String respBody = null; if(response.hasEntity()) { try{ - message = String.valueOf(response.getEntity(String.class)); + respBody = String.valueOf(response.getEntity(String.class)); + message = respBody; } catch (RuntimeException e) { // e.printStackTrace(); @@ -270,7 +272,9 @@ public class ApiClient { } throw new ApiException( response.getClientResponseStatus().getStatusCode(), - message); + message, + response.getHeaders(), + respBody); } } diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiException.java b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiException.java index 31bc8a0978a..515c21d85d4 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiException.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiException.java @@ -1,8 +1,13 @@ package io.swagger.client; +import java.util.Map; +import java.util.List; + public class ApiException extends Exception { - int code = 0; - String message = null; + private int code = 0; + private String message = null; + private Map> responseHeaders = null; + private String responseBody = null; public ApiException() {} @@ -11,19 +16,42 @@ public class ApiException extends Exception { this.message = message; } + public ApiException(int code, String message, Map> responseHeaders, String responseBody) { + this.code = code; + this.message = message; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + public int getCode() { return code; } - + public void setCode(int code) { this.code = code; } - + public String getMessage() { return message; } - + public void setMessage(String message) { this.message = message; } -} \ No newline at end of file + + public Map> getResponseHeaders() { + return responseHeaders; + } + + public void setResponseHeaders(Map> responseHeaders) { + this.responseHeaders = responseHeaders; + } + + public String getResponseBody() { + return responseBody; + } + + public void setResponseBody(String responseBody) { + this.responseBody = responseBody; + } +} From 7080983521c957be3144f8d8582e5037989c3bb0 Mon Sep 17 00:00:00 2001 From: wing328 Date: Tue, 2 Jun 2015 17:25:38 +0800 Subject: [PATCH 56/72] return exception instead of null for 404, add properties to api exception class --- ' | 458 ++++++++++++++++++ .../src/main/resources/php/APIClient.mustache | 25 +- .../main/resources/php/ApiException.mustache | 36 +- .../main/resources/php/configuration.mustache | 44 +- .../php/SwaggerClient-php/lib/APIClient.php | 25 +- .../SwaggerClient-php/lib/ApiException.php | 36 +- .../SwaggerClient-php/lib/Configuration.php | 44 +- samples/client/petstore/php/test.php | 9 +- 8 files changed, 606 insertions(+), 71 deletions(-) create mode 100644 ' diff --git a/' b/' new file mode 100644 index 00000000000..fdb14df5153 --- /dev/null +++ b/' @@ -0,0 +1,458 @@ +host = '{{basePath}}'; + } else { + $this->host = $host; + } + } + + /** + * add default header + * + * @param string $header_name header name (e.g. Token) + * @param string $header_value header value (e.g. 1z8wp3) + */ + public function addDefaultHeader($header_name, $header_value) { + if (!is_string($header_name)) + throw new \InvalidArgumentException('Header name must be a string.'); + + self::$default_header[$header_name] = $header_value; + } + + /** + * get the default header + * + * @return array default header + */ + public function getDefaultHeader() { + return self::$default_header; + } + + /** + * delete the default header based on header name + * + * @param string $header_name header name (e.g. Token) + */ + public function deleteDefaultHeader($header_name) { + unset(self::$default_header[$header_name]); + } + + /** + * set the user agent of the api client + * + * @param string $user_agent the user agent of the api client + */ + public function setUserAgent($user_agent) { + if (!is_string($user_agent)) + throw new \InvalidArgumentException('User-agent must be a string.'); + + $this->user_agent= $user_agent; + } + + /** + * get the user agent of the api client + * + * @return string user agent + */ + public function getUserAgent($user_agent) { + return $this->user_agent; + } + + /** + * set the HTTP timeout value + * + * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] + */ + public function setTimeout($seconds) { + if (!is_numeric($seconds) || $seconds < 0) + throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); + + $this->curl_timeout = $seconds; + } + + /** + * get the HTTP timeout value + * + * @return string HTTP timeout value + */ + public function getTimeout() { + return $this->curl_timeout; + } + + + /** + * Get API key (with prefix if set) + * @param string key name + * @return string API key with the prefix + */ + public function getApiKeyWithPrefix($apiKey) { + if (isset(Configuration::$apiKeyPrefix[$apiKey])) { + return Configuration::$apiKeyPrefix[$apiKey]." ".Configuration::$apiKey[$apiKey]; + } else if (isset(Configuration::$apiKey[$apiKey])) { + return Configuration::$apiKey[$apiKey]; + } else { + return; + } + } + + /** + * update hearder and query param based on authentication setting + * + * @param array $headerParams header parameters (by ref) + * @param array $queryParams query parameters (by ref) + * @param array $authSettings array of authentication scheme (e.g ['api_key']) + */ + public function updateParamsForAuth(&$headerParams, &$queryParams, $authSettings) + { + if (count($authSettings) == 0) + return; + + // one endpoint can have more than 1 auth settings + foreach($authSettings as $auth) { + // determine which one to use + switch($auth) { + {{#authMethods}} + case '{{name}}': + {{#isApiKey}}{{#isKeyInHeader}}$headerParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInHeader}}{{#isKeyInQuery}}$queryParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}$headerParams['Authorization'] = 'Basic '.base64_encode(Configuration::$username.":".Configuration::$password);{{/isBasic}} + {{#isOAuth}}//TODO support oauth{{/isOAuth}} + break; + {{/authMethods}} + default: + //TODO show warning about security definition not found + } + } + } + + /** + * @param string $resourcePath path to method endpoint + * @param string $method method to call + * @param array $queryParams parameters to be place in query URL + * @param array $postData parameters to be placed in POST body + * @param array $headerParams parameters to be place in request header + * @return mixed + */ + public function callApi($resourcePath, $method, $queryParams, $postData, + $headerParams, $authSettings) { + + $headers = array(); + + # determine authentication setting + $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); + + # construct the http header + if ($headerParams != null) { + # add default header + $headerParams = array_merge((array)self::$default_header, $headerParams); + + foreach ($headerParams as $key => $val) { + $headers[] = "$key: $val"; + } + } + + // form data + if ($postData and in_array('Content-Type: application/x-www-form-urlencoded', $headers)) { + $postData = http_build_query($postData); + } + else if ((is_object($postData) or is_array($postData)) and !in_array('Content-Type: multipart/form-data', $headers)) { // json model + $postData = json_encode($this->sanitizeForSerialization($postData)); + } + + $url = $this->host . $resourcePath; + + $curl = curl_init(); + // set timeout, if needed + if ($this->curl_timeout != 0) { + curl_setopt($curl, CURLOPT_TIMEOUT, $this->curl_timeout); + } + // return the result on success, rather than just TRUE + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + + if (! empty($queryParams)) { + $url = ($url . '?' . http_build_query($queryParams)); + } + + if ($method == self::$POST) { + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + } else if ($method == self::$PATCH) { + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PATCH"); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + } else if ($method == self::$PUT) { + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + } else if ($method == self::$DELETE) { + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE"); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + } else if ($method != self::$GET) { + throw new ApiException('Method ' . $method . ' is not recognized.'); + } + curl_setopt($curl, CURLOPT_URL, $url); + + // Set user agent + curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent); + + // debugging for curl + if (Configuration::$debug) { + error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, Configuration::$debug_file); + + curl_setopt($curl, CURLOPT_VERBOSE, 1); + curl_setopt($curl, CURLOPT_STDERR, fopen(Configuration::$debug_file, 'a')); + } else { + curl_setopt($curl, CURLOPT_VERBOSE, 0); + } + + // obtain the HTTP response headers + curl_setopt($curl, CURLOPT_HEADER, 1); + + // Make the request + $response = curl_exec($curl); + $response_info = curl_getinfo($curl); + + // debug HTTP response body + if (Configuration::$debug) { + error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($response, true)."\n~END~\n", 3, Configuration::$debug_file); + } + + // Handle the response + if ($response_info['http_code'] == 0) { + throw new ApiException("Api call to $url timed out: ".serialize($response_info), 0, null, null); + } else if ($response_info['http_code'] >= 200 && $response_info['http_code'] <= 299 ) { + $data = json_decode($response); + if (json_last_error() > 0) { // if response is a string + $data = $response; + } +// } else if ($response_info['http_code'] == 401) { +// throw new ApiException("Unauthorized API request to " . $url . +// ": " . serialize($response), 0, $response_info, $response); +// } else if ($response_info['http_code'] == 404) { +// $data = null; + } else { + + $http_header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); + $http_header = substr($response, 0, $http_header_size); + $http_body = substr($response, $http_header_size); + + throw new ApiException("[".$response_info['http_code']."] Error connecting to the API ($url)", + $response_info['http_code'], $http_header, $http_body); + } + return $data; + } + + /** + * Build a JSON POST object + */ + protected function sanitizeForSerialization($data) + { + if (is_scalar($data) || null === $data) { + $sanitized = $data; + } else if ($data instanceof \DateTime) { + $sanitized = $data->format(\DateTime::ISO8601); + } else if (is_array($data)) { + foreach ($data as $property => $value) { + $data[$property] = $this->sanitizeForSerialization($value); + } + $sanitized = $data; + } else if (is_object($data)) { + $values = array(); + foreach (array_keys($data::$swaggerTypes) as $property) { + $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); + } + $sanitized = $values; + } else { + $sanitized = (string)$data; + } + + return $sanitized; + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the path, by url-encoding. + * @param string $value a string which will be part of the path + * @return string the serialized object + */ + public static function toPathValue($value) { + return rawurlencode(self::toString($value)); + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the query, by imploding comma-separated if it's an object. + * If it's a string, pass through unchanged. It will be url-encoded + * later. + * @param object $object an object to be serialized to a string + * @return string the serialized object + */ + public static function toQueryValue($object) { + if (is_array($object)) { + return implode(',', $object); + } else { + return self::toString($object); + } + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the header. If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value a string which will be part of the header + * @return string the header string + */ + public static function toHeaderValue($value) { + return self::toString($value); + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the http body (form parameter). If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value the value of the form parameter + * @return string the form string + */ + public static function toFormValue($value) { + return self::toString($value); + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the parameter. If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value the value of the parameter + * @return string the header string + */ + public static function toString($value) { + if ($value instanceof \DateTime) { // datetime in ISO8601 format + return $value->format(\DateTime::ISO8601); + } + else { + return $value; + } + } + + /** + * Deserialize a JSON string into an object + * + * @param object $object object or primitive to be deserialized + * @param string $class class name is passed as a string + * @return object an instance of $class + */ + public static function deserialize($data, $class) + { + if (null === $data) { + $deserialized = null; + } elseif (substr($class, 0, 4) == 'map[') { + $inner = substr($class, 4, -1); + $values = array(); + if(strrpos($inner, ",") !== false) { + $subClass_array = explode(',', $inner, 2); + $subClass = $subClass_array[1]; + foreach ($data as $key => $value) { + $values[] = array($key => self::deserialize($value, $subClass)); + } + } + $deserialized = $values; + } elseif (strcasecmp(substr($class, 0, 6),'array[') == 0) { + $subClass = substr($class, 6, -1); + $values = array(); + foreach ($data as $key => $value) { + $values[] = self::deserialize($value, $subClass); + } + $deserialized = $values; + } elseif ($class == 'DateTime') { + $deserialized = new \DateTime($data); + } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool'))) { + settype($data, $class); + $deserialized = $data; + } else { + $class = "{{invokerPackage}}\\models\\".$class; + $instance = new $class(); + foreach ($instance::$swaggerTypes as $property => $type) { + $original_property_name = $instance::$attributeMap[$property]; + if (isset($original_property_name) && isset($data->$original_property_name)) { + $instance->$property = self::deserialize($data->$original_property_name, $type); + } + } + $deserialized = $instance; + } + + return $deserialized; + } + + /* + * return the header 'Accept' based on an array of Accept provided + * + * @param array[string] $accept Array of header + * @return string Accept (e.g. application/json) + */ + public static function selectHeaderAccept($accept) { + if (count($accept) === 0 or (count($accept) === 1 and $accept[0] === '')) { + return NULL; + } elseif (preg_grep("/application\/json/i", $accept)) { + return 'application/json'; + } else { + return implode(',', $accept); + } + } + + /* + * return the content type based on an array of content-type provided + * + * @param array[string] content_type_array Array fo content-type + * @return string Content-Type (e.g. application/json) + */ + public static function selectHeaderContentType($content_type) { + if (count($content_type) === 0 or (count($content_type) === 1 and $content_type[0] === '')) { + return 'application/json'; + } elseif (preg_grep("/application\/json/i", $content_type)) { + return 'application/json'; + } else { + return implode(',', $content_type); + } + } + +} + diff --git a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache index cadce36f64d..df7f508de69 100644 --- a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache @@ -245,33 +245,32 @@ class ApiClient { curl_setopt($curl, CURLOPT_VERBOSE, 0); } + // obtain the HTTP response headers + curl_setopt($curl, CURLOPT_HEADER, 1); + // Make the request $response = curl_exec($curl); + $http_header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); + $http_header = substr($response, 0, $http_header_size); + $http_body = substr($response, $http_header_size); $response_info = curl_getinfo($curl); // debug HTTP response body if (Configuration::$debug) { - error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($response, true)."\n~END~\n", 3, Configuration::$debug_file); + error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, Configuration::$debug_file); } // Handle the response if ($response_info['http_code'] == 0) { - throw new ApiException("TIMEOUT: api call to " . $url . - " took more than 5s to return", 0, $response_info, $response); + throw new ApiException("API call to $url timed out: ".serialize($response_info), 0, null, null); } else if ($response_info['http_code'] >= 200 && $response_info['http_code'] <= 299 ) { - $data = json_decode($response); + $data = json_decode($http_body); if (json_last_error() > 0) { // if response is a string - $data = $response; + $data = $http_body; } - } else if ($response_info['http_code'] == 401) { - throw new ApiException("Unauthorized API request to " . $url . - ": " . serialize($response), 0, $response_info, $response); - } else if ($response_info['http_code'] == 404) { - $data = null; } else { - throw new ApiException("Can't connect to the api: " . $url . - " response code: " . - $response_info['http_code'], 0, $response_info, $response); + throw new ApiException("[".$response_info['http_code']."] Error connecting to the API ($url)", + $response_info['http_code'], $http_header, $http_body); } return $data; } diff --git a/modules/swagger-codegen/src/main/resources/php/ApiException.mustache b/modules/swagger-codegen/src/main/resources/php/ApiException.mustache index 58a75eabeb1..d108c3d2902 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiException.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiException.mustache @@ -20,19 +20,39 @@ namespace {{invokerPackage}}; use \Exception; class ApiException extends Exception { - protected $response, $response_info; - public function __construct($message="", $code=0, $response_info=null, $response=null) { + /** + * The HTTP body of the server response. + */ + protected $response_body; + + /** + * The HTTP header of the server response. + */ + protected $response_headers; + + public function __construct($message="", $code=0, $responseHeaders=null, $responseBody=null) { parent::__construct($message, $code); - $this->response_info = $response_info; - $this->response = $response; + $this->response_headers = $responseHeaders; + $this->response_body = $responseBody; } - public function getResponse() { - return $this->response; + /** + * Get the HTTP response header + * + * @return string HTTP response header + */ + public function getResponseHeaders() { + return $this->response_headers; } - public function getResponseInfo() { - return $this->response_info; + /** + * Get the HTTP response body + * + * @return string HTTP response body + */ + public function getResponseBody() { + return $this->response_body; } + } diff --git a/modules/swagger-codegen/src/main/resources/php/configuration.mustache b/modules/swagger-codegen/src/main/resources/php/configuration.mustache index ea5f813b5e0..7099a2cb234 100644 --- a/modules/swagger-codegen/src/main/resources/php/configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/php/configuration.mustache @@ -19,28 +19,44 @@ namespace {{invokerPackage}}; class Configuration { - public static $PATCH = "PATCH"; - public static $POST = "POST"; - public static $GET = "GET"; - public static $PUT = "PUT"; - public static $DELETE = "DELETE"; - - // authentication setting + /** + * Associate array to store API key(s) + */ public static $apiKey = array(); + + /** + * Associate array to store API prefix (e.g. Bearer) + */ public static $apiKeyPrefix = array(); + + /** + * Username for HTTP basic authentication + */ public static $username = ''; + + /** + * Password for HTTP basic authentication + */ public static $password = ''; - // an instance of ApiClient + /** + * The default instance of ApiClient + */ public static $apiClient; - // debugging - public static $debug = false; // by default debugging is disabled - public static $debug_file = 'php://output'; //output debug log to STDOUT by default + /** + * Debug switch (default set to false) + */ + public static $debug = false; - /* - * manually initalize Api client - */ + /** + * Debug file location (log to STDOUT by default) + */ + public static $debug_file = 'php://output'; + + /* + * manually initalize ApiClient + */ public static function init() { if (self::$apiClient === null) self::$apiClient = new ApiClient(); diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php index 5b3289b5a29..11b06862875 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php @@ -250,33 +250,32 @@ class ApiClient { curl_setopt($curl, CURLOPT_VERBOSE, 0); } + // obtain the HTTP response headers + curl_setopt($curl, CURLOPT_HEADER, 1); + // Make the request $response = curl_exec($curl); + $http_header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); + $http_header = substr($response, 0, $http_header_size); + $http_body = substr($response, $http_header_size); $response_info = curl_getinfo($curl); // debug HTTP response body if (Configuration::$debug) { - error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($response, true)."\n~END~\n", 3, Configuration::$debug_file); + error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, Configuration::$debug_file); } // Handle the response if ($response_info['http_code'] == 0) { - throw new ApiException("TIMEOUT: api call to " . $url . - " took more than 5s to return", 0, $response_info, $response); + throw new ApiException("API call to $url timed out: ".serialize($response_info), 0, null, null); } else if ($response_info['http_code'] >= 200 && $response_info['http_code'] <= 299 ) { - $data = json_decode($response); + $data = json_decode($http_body); if (json_last_error() > 0) { // if response is a string - $data = $response; + $data = $http_body; } - } else if ($response_info['http_code'] == 401) { - throw new ApiException("Unauthorized API request to " . $url . - ": " . serialize($response), 0, $response_info, $response); - } else if ($response_info['http_code'] == 404) { - $data = null; } else { - throw new ApiException("Can't connect to the api: " . $url . - " response code: " . - $response_info['http_code'], 0, $response_info, $response); + throw new ApiException("[".$response_info['http_code']."] Error connecting to the API ($url)", + $response_info['http_code'], $http_header, $http_body); } return $data; } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php b/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php index 8b8244718ee..40158cf76e6 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php @@ -20,19 +20,39 @@ namespace SwaggerClient; use \Exception; class ApiException extends Exception { - protected $response, $response_info; - public function __construct($message="", $code=0, $response_info=null, $response=null) { + /** + * The HTTP body of the server response. + */ + protected $response_body; + + /** + * The HTTP header of the server response. + */ + protected $response_headers; + + public function __construct($message="", $code=0, $responseHeaders=null, $responseBody=null) { parent::__construct($message, $code); - $this->response_info = $response_info; - $this->response = $response; + $this->response_headers = $responseHeaders; + $this->response_body = $responseBody; } - public function getResponse() { - return $this->response; + /** + * Get the HTTP response header + * + * @return string HTTP response header + */ + public function getResponseHeaders() { + return $this->response_headers; } - public function getResponseInfo() { - return $this->response_info; + /** + * Get the HTTP response body + * + * @return string HTTP response body + */ + public function getResponseBody() { + return $this->response_body; } + } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php index a3412c93eb6..8a0dc734a0d 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php @@ -19,28 +19,44 @@ namespace SwaggerClient; class Configuration { - public static $PATCH = "PATCH"; - public static $POST = "POST"; - public static $GET = "GET"; - public static $PUT = "PUT"; - public static $DELETE = "DELETE"; - - // authentication setting + /** + * Associate array to store API key(s) + */ public static $apiKey = array(); + + /** + * Associate array to store API prefix (e.g. Bearer) + */ public static $apiKeyPrefix = array(); + + /** + * Username for HTTP basic authentication + */ public static $username = ''; + + /** + * Password for HTTP basic authentication + */ public static $password = ''; - // an instance of ApiClient + /** + * The default instance of ApiClient + */ public static $apiClient; - // debugging - public static $debug = false; // by default debugging is disabled - public static $debug_file = 'php://output'; //output debug log to STDOUT by default + /** + * Debug switch (default set to false) + */ + public static $debug = false; - /* - * manually initalize Api client - */ + /** + * Debug file location (log to STDOUT by default) + */ + public static $debug_file = 'php://output'; + + /* + * manually initalize ApiClient + */ public static function init() { if (self::$apiClient === null) self::$apiClient = new ApiClient(); diff --git a/samples/client/petstore/php/test.php b/samples/client/petstore/php/test.php index 0721d7614f2..a358ea5df45 100644 --- a/samples/client/petstore/php/test.php +++ b/samples/client/petstore/php/test.php @@ -17,8 +17,15 @@ try { // return Pet (model) $response = $pet_api->getPetById($petId); var_dump($response); -} catch (Exception $e) { + + // test upload file (exception) + $upload_response = $pet_api->uploadFile($petId, "test meta", NULL); + +} catch (SwaggerClient\ApiException $e) { echo 'Caught exception: ', $e->getMessage(), "\n"; + echo 'HTTP response headers: ', $e->getResponseHeaders(), "\n"; + echo 'HTTP response body: ', $e->getResponseBody(), "\n"; + echo 'HTTP status code: ', $e->getCode(), "\n"; } ?> From 2d6a7092e371f609ed6c3feaaa86201504f7ba8d Mon Sep 17 00:00:00 2001 From: wing328 Date: Tue, 2 Jun 2015 20:43:11 +0800 Subject: [PATCH 57/72] removed unused file --- ' | 458 -------------------------------------------------------------- 1 file changed, 458 deletions(-) delete mode 100644 ' diff --git a/' b/' deleted file mode 100644 index fdb14df5153..00000000000 --- a/' +++ /dev/null @@ -1,458 +0,0 @@ -host = '{{basePath}}'; - } else { - $this->host = $host; - } - } - - /** - * add default header - * - * @param string $header_name header name (e.g. Token) - * @param string $header_value header value (e.g. 1z8wp3) - */ - public function addDefaultHeader($header_name, $header_value) { - if (!is_string($header_name)) - throw new \InvalidArgumentException('Header name must be a string.'); - - self::$default_header[$header_name] = $header_value; - } - - /** - * get the default header - * - * @return array default header - */ - public function getDefaultHeader() { - return self::$default_header; - } - - /** - * delete the default header based on header name - * - * @param string $header_name header name (e.g. Token) - */ - public function deleteDefaultHeader($header_name) { - unset(self::$default_header[$header_name]); - } - - /** - * set the user agent of the api client - * - * @param string $user_agent the user agent of the api client - */ - public function setUserAgent($user_agent) { - if (!is_string($user_agent)) - throw new \InvalidArgumentException('User-agent must be a string.'); - - $this->user_agent= $user_agent; - } - - /** - * get the user agent of the api client - * - * @return string user agent - */ - public function getUserAgent($user_agent) { - return $this->user_agent; - } - - /** - * set the HTTP timeout value - * - * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] - */ - public function setTimeout($seconds) { - if (!is_numeric($seconds) || $seconds < 0) - throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); - - $this->curl_timeout = $seconds; - } - - /** - * get the HTTP timeout value - * - * @return string HTTP timeout value - */ - public function getTimeout() { - return $this->curl_timeout; - } - - - /** - * Get API key (with prefix if set) - * @param string key name - * @return string API key with the prefix - */ - public function getApiKeyWithPrefix($apiKey) { - if (isset(Configuration::$apiKeyPrefix[$apiKey])) { - return Configuration::$apiKeyPrefix[$apiKey]." ".Configuration::$apiKey[$apiKey]; - } else if (isset(Configuration::$apiKey[$apiKey])) { - return Configuration::$apiKey[$apiKey]; - } else { - return; - } - } - - /** - * update hearder and query param based on authentication setting - * - * @param array $headerParams header parameters (by ref) - * @param array $queryParams query parameters (by ref) - * @param array $authSettings array of authentication scheme (e.g ['api_key']) - */ - public function updateParamsForAuth(&$headerParams, &$queryParams, $authSettings) - { - if (count($authSettings) == 0) - return; - - // one endpoint can have more than 1 auth settings - foreach($authSettings as $auth) { - // determine which one to use - switch($auth) { - {{#authMethods}} - case '{{name}}': - {{#isApiKey}}{{#isKeyInHeader}}$headerParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInHeader}}{{#isKeyInQuery}}$queryParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}$headerParams['Authorization'] = 'Basic '.base64_encode(Configuration::$username.":".Configuration::$password);{{/isBasic}} - {{#isOAuth}}//TODO support oauth{{/isOAuth}} - break; - {{/authMethods}} - default: - //TODO show warning about security definition not found - } - } - } - - /** - * @param string $resourcePath path to method endpoint - * @param string $method method to call - * @param array $queryParams parameters to be place in query URL - * @param array $postData parameters to be placed in POST body - * @param array $headerParams parameters to be place in request header - * @return mixed - */ - public function callApi($resourcePath, $method, $queryParams, $postData, - $headerParams, $authSettings) { - - $headers = array(); - - # determine authentication setting - $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); - - # construct the http header - if ($headerParams != null) { - # add default header - $headerParams = array_merge((array)self::$default_header, $headerParams); - - foreach ($headerParams as $key => $val) { - $headers[] = "$key: $val"; - } - } - - // form data - if ($postData and in_array('Content-Type: application/x-www-form-urlencoded', $headers)) { - $postData = http_build_query($postData); - } - else if ((is_object($postData) or is_array($postData)) and !in_array('Content-Type: multipart/form-data', $headers)) { // json model - $postData = json_encode($this->sanitizeForSerialization($postData)); - } - - $url = $this->host . $resourcePath; - - $curl = curl_init(); - // set timeout, if needed - if ($this->curl_timeout != 0) { - curl_setopt($curl, CURLOPT_TIMEOUT, $this->curl_timeout); - } - // return the result on success, rather than just TRUE - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - - if (! empty($queryParams)) { - $url = ($url . '?' . http_build_query($queryParams)); - } - - if ($method == self::$POST) { - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); - } else if ($method == self::$PATCH) { - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PATCH"); - curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); - } else if ($method == self::$PUT) { - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT"); - curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); - } else if ($method == self::$DELETE) { - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE"); - curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); - } else if ($method != self::$GET) { - throw new ApiException('Method ' . $method . ' is not recognized.'); - } - curl_setopt($curl, CURLOPT_URL, $url); - - // Set user agent - curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent); - - // debugging for curl - if (Configuration::$debug) { - error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, Configuration::$debug_file); - - curl_setopt($curl, CURLOPT_VERBOSE, 1); - curl_setopt($curl, CURLOPT_STDERR, fopen(Configuration::$debug_file, 'a')); - } else { - curl_setopt($curl, CURLOPT_VERBOSE, 0); - } - - // obtain the HTTP response headers - curl_setopt($curl, CURLOPT_HEADER, 1); - - // Make the request - $response = curl_exec($curl); - $response_info = curl_getinfo($curl); - - // debug HTTP response body - if (Configuration::$debug) { - error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($response, true)."\n~END~\n", 3, Configuration::$debug_file); - } - - // Handle the response - if ($response_info['http_code'] == 0) { - throw new ApiException("Api call to $url timed out: ".serialize($response_info), 0, null, null); - } else if ($response_info['http_code'] >= 200 && $response_info['http_code'] <= 299 ) { - $data = json_decode($response); - if (json_last_error() > 0) { // if response is a string - $data = $response; - } -// } else if ($response_info['http_code'] == 401) { -// throw new ApiException("Unauthorized API request to " . $url . -// ": " . serialize($response), 0, $response_info, $response); -// } else if ($response_info['http_code'] == 404) { -// $data = null; - } else { - - $http_header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); - $http_header = substr($response, 0, $http_header_size); - $http_body = substr($response, $http_header_size); - - throw new ApiException("[".$response_info['http_code']."] Error connecting to the API ($url)", - $response_info['http_code'], $http_header, $http_body); - } - return $data; - } - - /** - * Build a JSON POST object - */ - protected function sanitizeForSerialization($data) - { - if (is_scalar($data) || null === $data) { - $sanitized = $data; - } else if ($data instanceof \DateTime) { - $sanitized = $data->format(\DateTime::ISO8601); - } else if (is_array($data)) { - foreach ($data as $property => $value) { - $data[$property] = $this->sanitizeForSerialization($value); - } - $sanitized = $data; - } else if (is_object($data)) { - $values = array(); - foreach (array_keys($data::$swaggerTypes) as $property) { - $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); - } - $sanitized = $values; - } else { - $sanitized = (string)$data; - } - - return $sanitized; - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the path, by url-encoding. - * @param string $value a string which will be part of the path - * @return string the serialized object - */ - public static function toPathValue($value) { - return rawurlencode(self::toString($value)); - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the query, by imploding comma-separated if it's an object. - * If it's a string, pass through unchanged. It will be url-encoded - * later. - * @param object $object an object to be serialized to a string - * @return string the serialized object - */ - public static function toQueryValue($object) { - if (is_array($object)) { - return implode(',', $object); - } else { - return self::toString($object); - } - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the header. If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value a string which will be part of the header - * @return string the header string - */ - public static function toHeaderValue($value) { - return self::toString($value); - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the http body (form parameter). If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value the value of the form parameter - * @return string the form string - */ - public static function toFormValue($value) { - return self::toString($value); - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the parameter. If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value the value of the parameter - * @return string the header string - */ - public static function toString($value) { - if ($value instanceof \DateTime) { // datetime in ISO8601 format - return $value->format(\DateTime::ISO8601); - } - else { - return $value; - } - } - - /** - * Deserialize a JSON string into an object - * - * @param object $object object or primitive to be deserialized - * @param string $class class name is passed as a string - * @return object an instance of $class - */ - public static function deserialize($data, $class) - { - if (null === $data) { - $deserialized = null; - } elseif (substr($class, 0, 4) == 'map[') { - $inner = substr($class, 4, -1); - $values = array(); - if(strrpos($inner, ",") !== false) { - $subClass_array = explode(',', $inner, 2); - $subClass = $subClass_array[1]; - foreach ($data as $key => $value) { - $values[] = array($key => self::deserialize($value, $subClass)); - } - } - $deserialized = $values; - } elseif (strcasecmp(substr($class, 0, 6),'array[') == 0) { - $subClass = substr($class, 6, -1); - $values = array(); - foreach ($data as $key => $value) { - $values[] = self::deserialize($value, $subClass); - } - $deserialized = $values; - } elseif ($class == 'DateTime') { - $deserialized = new \DateTime($data); - } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool'))) { - settype($data, $class); - $deserialized = $data; - } else { - $class = "{{invokerPackage}}\\models\\".$class; - $instance = new $class(); - foreach ($instance::$swaggerTypes as $property => $type) { - $original_property_name = $instance::$attributeMap[$property]; - if (isset($original_property_name) && isset($data->$original_property_name)) { - $instance->$property = self::deserialize($data->$original_property_name, $type); - } - } - $deserialized = $instance; - } - - return $deserialized; - } - - /* - * return the header 'Accept' based on an array of Accept provided - * - * @param array[string] $accept Array of header - * @return string Accept (e.g. application/json) - */ - public static function selectHeaderAccept($accept) { - if (count($accept) === 0 or (count($accept) === 1 and $accept[0] === '')) { - return NULL; - } elseif (preg_grep("/application\/json/i", $accept)) { - return 'application/json'; - } else { - return implode(',', $accept); - } - } - - /* - * return the content type based on an array of content-type provided - * - * @param array[string] content_type_array Array fo content-type - * @return string Content-Type (e.g. application/json) - */ - public static function selectHeaderContentType($content_type) { - if (count($content_type) === 0 or (count($content_type) === 1 and $content_type[0] === '')) { - return 'application/json'; - } elseif (preg_grep("/application\/json/i", $content_type)) { - return 'application/json'; - } else { - return implode(',', $content_type); - } - } - -} - From 1a75489b42d2be4ae6884d1b58421f54c538e7db Mon Sep 17 00:00:00 2001 From: Andrew B Date: Tue, 2 Jun 2015 09:04:50 -0700 Subject: [PATCH 58/72] Enabling cli config options for android generator --- .../languages/AndroidClientCodegen.java | 117 +++++++++++++++--- .../resources/android-java/build.mustache | 4 +- .../resources/android-java/jsonUtil.mustache | 2 +- 3 files changed, 100 insertions(+), 23 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/AndroidClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/AndroidClientCodegen.java index 62fc70efdea..377c8de24d9 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/AndroidClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/AndroidClientCodegen.java @@ -47,26 +47,6 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi "native", "super", "while") ); - additionalProperties.put("invokerPackage", invokerPackage); - additionalProperties.put("groupId", groupId); - additionalProperties.put("artifactId", artifactId); - additionalProperties.put("artifactVersion", artifactVersion); - - supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); - additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin); - - supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle")); - supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle")); - supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml")); - supportingFiles.add(new SupportingFile("apiInvoker.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.java")); - supportingFiles.add(new SupportingFile("httpPatch.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "HttpPatch.java")); - supportingFiles.add(new SupportingFile("jsonUtil.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java")); - supportingFiles.add(new SupportingFile("apiException.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java")); - languageSpecificPrimitives = new HashSet( Arrays.asList( "String", @@ -80,6 +60,13 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi ); instantiationTypes.put("array", "ArrayList"); instantiationTypes.put("map", "HashMap"); + + cliOptions.add(new CliOption("invokerPackage", "root package to use for the generated code")); + cliOptions.add(new CliOption("groupId", "groupId for use in the generated build.gradle and pom.xml")); + cliOptions.add(new CliOption("artifactId", "artifactId for use in the generated build.gradle and pom.xml")); + cliOptions.add(new CliOption("artifactVersion", "artifact version for use in the generated build.gradle and pom.xml")); + cliOptions.add(new CliOption("sourceFolder", "source folder for generated code")); + cliOptions.add(new CliOption("useAndroidMavenGradlePlugin", "A flag to toggle android-maven gradle plugin. Default is true.")); } @Override @@ -177,6 +164,96 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi return camelize(operationId, true); } + + @Override + public void processOpts() { + super.processOpts(); + + if(additionalProperties.containsKey("invokerPackage")) { + this.setInvokerPackage((String)additionalProperties.get("invokerPackage")); + } + else{ + //not set, use default to be passed to template + additionalProperties.put("invokerPackage", invokerPackage); + } + + if(additionalProperties.containsKey("groupId")) { + this.setGroupId((String)additionalProperties.get("groupId")); + } + else{ + //not set, use to be passed to template + additionalProperties.put("groupId", groupId); + } + + if(additionalProperties.containsKey("artifactId")) { + this.setArtifactId((String)additionalProperties.get("artifactId")); + } + else{ + //not set, use to be passed to template + additionalProperties.put("artifactId", artifactId); + } + + if(additionalProperties.containsKey("artifactVersion")) { + this.setArtifactVersion((String)additionalProperties.get("artifactVersion")); + } + else{ + //not set, use to be passed to template + additionalProperties.put("artifactVersion", artifactVersion); + } + + if(additionalProperties.containsKey("sourceFolder")) { + this.setSourceFolder((String)additionalProperties.get("sourceFolder")); + } + if(additionalProperties.containsKey("useAndroidMavenGradlePlugin")) { + this.setUseAndroidMavenGradlePlugin((Boolean)additionalProperties.get("useAndroidMavenGradlePlugin")); + } + else{ + additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin); + } + + supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); + additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin); + + supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle")); + supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle")); + supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml")); + supportingFiles.add(new SupportingFile("apiInvoker.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.java")); + supportingFiles.add(new SupportingFile("httpPatch.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "HttpPatch.java")); + supportingFiles.add(new SupportingFile("jsonUtil.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java")); + supportingFiles.add(new SupportingFile("apiException.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java")); + } + + public Boolean getUseAndroidMavenGradlePlugin() { + return useAndroidMavenGradlePlugin; + } + + public void setUseAndroidMavenGradlePlugin(Boolean useAndroidMavenGradlePlugin) { + this.useAndroidMavenGradlePlugin = useAndroidMavenGradlePlugin; + } + + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } } diff --git a/modules/swagger-codegen/src/main/resources/android-java/build.mustache b/modules/swagger-codegen/src/main/resources/android-java/build.mustache index 62a56bf066e..66fcef2a371 100644 --- a/modules/swagger-codegen/src/main/resources/android-java/build.mustache +++ b/modules/swagger-codegen/src/main/resources/android-java/build.mustache @@ -60,10 +60,10 @@ dependencies { compile "com.google.code.gson:gson:$gson_version" compile "org.apache.httpcomponents:httpcore:$httpclient_version" compile "org.apache.httpcomponents:httpclient:$httpclient_version" - compile ("org.apache.httpcomponents:httpcore:$httpcore_version") { + compile ("org.apache.httpcomponents:httpcore:$httpclient_version") { exclude(group: 'org.apache.httpcomponents', module: 'httpclient') } - compile ("org.apache.httpcomponents:httpmime:$httpmime_version") { + compile ("org.apache.httpcomponents:httpmime:$httpclient_version") { exclude(group: 'org.apache.httpcomponents', module: 'httpclient') } testCompile "junit:junit:$junit_version" diff --git a/modules/swagger-codegen/src/main/resources/android-java/jsonUtil.mustache b/modules/swagger-codegen/src/main/resources/android-java/jsonUtil.mustache index 3a6ff4111d1..ae8d18d3731 100644 --- a/modules/swagger-codegen/src/main/resources/android-java/jsonUtil.mustache +++ b/modules/swagger-codegen/src/main/resources/android-java/jsonUtil.mustache @@ -5,7 +5,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import java.lang.reflect.Type; import java.util.List; -import io.swagger.client.model.*; +import {{modelPackage}}.*; public class JsonUtil { public static GsonBuilder gsonBuilder; From 3d16d8b2b6aecc5d281335428803012905958a43 Mon Sep 17 00:00:00 2001 From: wing328 Date: Wed, 3 Jun 2015 08:34:45 +0800 Subject: [PATCH 59/72] fix header --- :w | 290 ++++++++++++++++++ .../main/resources/perl/APIClient.mustache | 82 ++++- .../resources/perl/Configuration.mustache | 6 + .../src/main/resources/perl/api.mustache | 11 +- .../perl/lib/WWW/SwaggerClient/APIClient.pm | 88 +++++- .../lib/WWW/SwaggerClient/Configuration.pm | 6 + .../perl/lib/WWW/SwaggerClient/PetApi.pm | 52 +++- .../perl/lib/WWW/SwaggerClient/StoreApi.pm | 32 +- .../perl/lib/WWW/SwaggerClient/UserApi.pm | 48 ++- samples/client/petstore/perl/test.pl | 2 + 10 files changed, 553 insertions(+), 64 deletions(-) create mode 100644 :w diff --git a/:w b/:w new file mode 100644 index 00000000000..b34a3de344b --- /dev/null +++ b/:w @@ -0,0 +1,290 @@ +package WWW::{{invokerPackage}}::ApiClient; + +use strict; +use warnings; +use utf8; + +use MIME::Base64; +use LWP::UserAgent; +use HTTP::Headers; +use HTTP::Response; +use HTTP::Request::Common qw(DELETE POST GET HEAD PUT); +use HTTP::Status; +use URI::Query; +use JSON; +use URI::Escape; +use Scalar::Util; +use Log::Any qw($log); +use Carp; +use Module::Runtime qw(use_module); + +use WWW::{{invokerPackage}}::Configuration; + +sub new +{ + my $class = shift; + my (%args) = ( + 'ua' => LWP::UserAgent->new, + 'base_url' => '{{basePath}}', + @_ + ); + + return bless \%args, $class; +} + +# Set the user agent of the API client +# +# @param string $user_agent The user agent of the API client +# +sub set_user_agent { + my ($self, $user_agent) = @_; + $self->{http_user_agent}= $user_agent; +} + +# Set timeout +# +# @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] +# +sub set_timeout { + my ($self, $seconds) = @_; + if (!looks_like_number($seconds)) { + croak('Timeout variable must be numeric.'); + } + $self->{http_timeout} = $seconds; +} + +# make the HTTP request +# @param string $resourcePath path to method endpoint +# @param string $method method to call +# @param array $queryParams parameters to be place in query URL +# @param array $postData parameters to be placed in POST body +# @param array $headerParams parameters to be place in request header +# @return mixed +sub call_api { + my $self = shift; + my ($resource_path, $method, $query_params, $post_params, $header_params, $body_data, $auth_settings) = @_; + + my $headers = HTTP::Headers->new(%$header_params); + + my $_url = $self->{base_url} . $resource_path; + + # build query + if (%$query_params) { + $_url = ($_url . '?' . eval { URI::Query->new($query_params)->stringify }); + } + + # update parameters based on authentication settings + update_params_for_auth(\$query_params, \$header_params, \$auth_settings); + + # body data + $body_data = to_json($body_data->to_hash) if defined $body_data && $body_data->can('to_hash'); # model to json string + my $_body_data = %$post_params ? $post_params : $body_data; + + # Make the HTTP request + my $_request; + if ($method eq 'POST') { + # multipart + my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? + 'form-data' : $header_params->{'Content-Type'}; + + $_request = POST($_url, Accept => $header_params->{Accept}, + Content_Type => $_content_type, Content => $_body_data); + } + elsif ($method eq 'PUT') { + # multipart + my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? + 'form-data' : $header_params->{'Content-Type'}; + $_request = PUT($_url, Accept => $header_params->{Accept}, + Content_Type => $_content_type, Content => $_body_data); + } + elsif ($method eq 'GET') { + $_request = GET($_url, Accept => $header_params->{'Accept'}, + Content_Type => $header_params->{'Content-Type'}); + } + elsif ($method eq 'HEAD') { + $_request = HEAD($_url, Accept => $header_params->{'Accept'}, + Content_Type => $header_params->{'Content-Type'}); + } + elsif ($method eq 'DELETE') { #TODO support form data + $_request = DELETE($_url, Accept => $header_params->{'Accept'}, + Content_Type => $header_params->{'Content-Type'}, Content => $_body_data); + } + elsif ($method eq 'PATCH') { #TODO + } + else { + } + + $self->{ua}->timeout($self->{http_timeout} || $WWW::{{invokerPackage}}::Configuration::http_timeout); + $self->{ua}->agent($self->{http_user_agent} || $WWW::{{invokerPackage}}::Configuration::http_user_agent); + + my $_response = $self->{ua}->request($_request); + + unless ($_response->is_success) { + croak("API Exception(".$_response->code."): ".$_response->message); + } + + return $_response->content; + +} + +# Take value and turn it into a string suitable for inclusion in +# the path, by url-encoding. +# @param string $value a string which will be part of the path +# @return string the serialized object +sub to_path_value { + my ($self, $value) = @_; + return uri_escape($self->to_string($value)); +} + + +# Take value and turn it into a string suitable for inclusion in +# the query, by imploding comma-separated if it's an object. +# If it's a string, pass through unchanged. It will be url-encoded +# later. +# @param object $object an object to be serialized to a string +# @return string the serialized object +sub to_query_value { + my ($self, $object) = @_; + if (is_array($object)) { + return implode(',', $object); + } else { + return $self->to_string($object); + } +} + + +# Take value and turn it into a string suitable for inclusion in +# the header. If it's a string, pass through unchanged +# If it's a datetime object, format it in ISO8601 +# @param string $value a string which will be part of the header +# @return string the header string +sub to_header_value { + my ($self, $value) = @_; + return $self->to_string($value); +} + +# Take value and turn it into a string suitable for inclusion in +# the http body (form parameter). If it's a string, pass through unchanged +# If it's a datetime object, format it in ISO8601 +# @param string $value the value of the form parameter +# @return string the form string +sub to_form_value { + my ($self, $value) = @_; + return $self->to_string($value); +} + +# Take value and turn it into a string suitable for inclusion in +# the parameter. If it's a string, pass through unchanged +# If it's a datetime object, format it in ISO8601 +# @param string $value the value of the parameter +# @return string the header string +sub to_string { + my ($self, $value) = @_; + if (ref($value) eq "DateTime") { # datetime in ISO8601 format + return $value->datetime(); + } + else { + return $value; + } +} + +# Deserialize a JSON string into an object +# +# @param string $class class name is passed as a string +# @param string $data data of the body +# @return object an instance of $class +sub deserialize +{ + my ($self, $class, $data) = @_; + $log->debugf("deserializing %s for %s", $data, $class); + my $_result; + + if (not defined $data) { + return undef; + } elsif ( lc(substr($class, 0, 4)) eq 'map[') { #hash + $_result = \(json_decode $data); + } elsif ( lc(substr($class, 0, 6)) eq 'array[' ) { # array of data + return $data if $data eq '[]'; # return if empty array + + my $_sub_class = substr($class, 6, -1); + my @_json_data = json_decode $data; + my @_values = (); + foreach my $_value (@_json_data) { + push @_values, $self->deserialize($_sub_class, $_value); + } + $_result = \@_values; + } elsif ($class eq 'DateTime') { + $_result = DateTime->from_epoch(epoch => str2time($data)); + } elsif (grep /^$data$/, ('string', 'int', 'float', 'bool')) { #TODO revise the primitive type + $_result= $data; + } else { # model + my $_instance = use_module("WWW::{{invokerPackage}}::Object::$class")->new; + $_result = $_instance->from_hash(decode_json $data); + } + + return $_result; + +} + +# return 'Accept' based on an array of accept provided +# @param [Array] header_accept_array Array fo 'Accept' +# @return String Accept (e.g. application/json) +sub select_header_accept +{ + my ($self, @header) = @_; + + if (@header == 0 || (@header == 1 && $header[0] eq '')) { + return undef; + } elsif (grep(/^application\/json$/i, @header)) { + return 'application/json'; + } else { + return join(',', @header); + } + +} + +# return the content type based on an array of content-type provided +# @param [Array] content_type_array Array fo content-type +# @return String Content-Type (e.g. application/json) +sub select_header_content_type +{ + my ($self, @header) = @_; + + if (@header == 0 || (@header == 1 && $header[0] eq '')) { + return 'application/json'; # default to application/json + } elsif (grep(/^application\/json$/i, @header)) { + return 'application/json'; + } else { + return join(',', @header); + } + +} + +# update hearder and query param based on authentication setting +# +# @param array $headerParams header parameters (by ref) +# @param array $queryParams query parameters (by ref) +# @param array $authSettings array of authentication scheme (e.g ['api_key']) +sub update_params_for_auth { + my ($self, $header_params, $query_params, $auth_settings) = @_; + + return if (scalar(@$auth_settings) == 0) + + # one endpoint can have more than 1 auth settings + foreach my $auth (@$auth_settings) { + # determine which one to use + if (!defined($auth)) { + } + {{#authMethods}} + elsif ($auth eq '{{name}}') { + {{#isApiKey}}{{#isKeyInHeader}}$header_params->{'{{keyParamName}}'} = $self->get_api_key_with_prefix('{{keyParamName}}');{{/isKeyInHeader}}{{#isKeyInQuery}}$query_params->{'{{keyParamName}}'} = $self->get_api_key_with_prefix('{{keyParamName}}');{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}$header_params->{'Authorization'} = 'Basic '.encode_base64(Configuration::username.":".Configuration::password);{{/isBasic}} + {{#isOAuth}}//TODO support oauth{{/isOAuth}} + }{{/authMethods}} + else { + //TODO show warning about security definition not found + } + } +} + + +1; diff --git a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache index d5fa48ac6d9..2b0f39a41cd 100644 --- a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache @@ -4,6 +4,7 @@ use strict; use warnings; use utf8; +use MIME::Base64; use LWP::UserAgent; use HTTP::Headers; use HTTP::Response; @@ -61,9 +62,11 @@ sub set_timeout { # @return mixed sub call_api { my $self = shift; - my ($resource_path, $method, $query_params, $post_params, $header_params, $body_data) = @_; + my ($resource_path, $method, $query_params, $post_params, $header_params, $body_data, $auth_settings) = @_; + + # update parameters based on authentication settings + $self->update_params_for_auth($header_params, $query_params, $auth_settings); - my $headers = HTTP::Headers->new(%$header_params); my $_url = $self->{base_url} . $resource_path; @@ -72,6 +75,7 @@ sub call_api { $_url = ($_url . '?' . eval { URI::Query->new($query_params)->stringify }); } + # body data $body_data = to_json($body_data->to_hash) if defined $body_data && $body_data->can('to_hash'); # model to json string my $_body_data = %$post_params ? $post_params : $body_data; @@ -82,28 +86,43 @@ sub call_api { # multipart my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; + $header_params->{'Content-Type'} = $_content_type; + my $headers = HTTP::Headers->new(%$header_params); + + #$_request = POST($_url, Accept => $header_params->{Accept}, + # Content_Type => $_content_type, Content => $_body_data); + $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) - $_request = POST($_url, Accept => $header_params->{Accept}, - Content_Type => $_content_type, Content => $_body_data); } elsif ($method eq 'PUT') { # multipart my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; - $_request = PUT($_url, Accept => $header_params->{Accept}, - Content_Type => $_content_type, Content => $_body_data); + $header_params->{'Content-Type'} = $_content_type; + my $headers = HTTP::Headers->new(%$header_params); + + #$_request = PUT($_url, Accept => $header_params->{Accept}, + # Content_Type => $_content_type, Content => $_body_data); + $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) + } elsif ($method eq 'GET') { - $_request = GET($_url, Accept => $header_params->{'Accept'}, - Content_Type => $header_params->{'Content-Type'}); + my $headers = HTTP::Headers->new(%$header_params); + #$_request = GET($_url, Accept => $header_params->{'Accept'}, + # Content_Type => $header_params->{'Content-Type'}); + $_request = HTTP::Request->new( $method, $_url, $headers) } elsif ($method eq 'HEAD') { - $_request = HEAD($_url, Accept => $header_params->{'Accept'}, - Content_Type => $header_params->{'Content-Type'}); + my $headers = HTTP::Headers->new(%$header_params); + #$_request = HEAD($_url, Accept => $header_params->{'Accept'}, + # Content_Type => $header_params->{'Content-Type'}); + $_request = HTTP::Request->new( $method, $_url, $headers) } elsif ($method eq 'DELETE') { #TODO support form data - $_request = DELETE($_url, Accept => $header_params->{'Accept'}, - Content_Type => $header_params->{'Content-Type'}, Content => $_body_data); + my $headers = HTTP::Headers->new(%$header_params); + #$_request = DELETE($_url, Accept => $header_params->{'Accept'}, + # Content_Type => $header_params->{'Content-Type'}, Content => $_body_data); + $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) } elsif ($method eq 'PATCH') { #TODO } @@ -256,5 +275,44 @@ sub select_header_content_type } +# Get API key (with prefix if set) +# @param string key name +# @return string API key with the prefix +sub get_api_key_with_prefix +{ + my ($self, $api_key) = @_; + if ($WWW::{{invokerPackage}}::Configuration::api_key_prefix->{$api_key}) { + return $WWW::{{invokerPackage}}::Configuration::api_key_prefix->{$api_key}." ".$WWW::{{invokerPackage}}::Configuration::api_key->{$api_key}; + } else { + return $WWW::{{invokerPackage}}::Configuration::api_key->{$api_key}; + } +} + +# update hearder and query param based on authentication setting +# +# @param array $headerParams header parameters (by ref) +# @param array $queryParams query parameters (by ref) +# @param array $authSettings array of authentication scheme (e.g ['api_key']) +sub update_params_for_auth { + my ($self, $header_params, $query_params, $auth_settings) = @_; + + return if (!defined($auth_settings) || scalar(@$auth_settings) == 0); + + # one endpoint can have more than 1 auth settings + foreach my $auth (@$auth_settings) { + # determine which one to use + if (!defined($auth)) { + } + {{#authMethods}}elsif ($auth eq '{{name}}') { + {{#isApiKey}}{{#isKeyInHeader}}$header_params->{'{{keyParamName}}'} = $self->get_api_key_with_prefix('{{keyParamName}}');{{/isKeyInHeader}}{{#isKeyInQuery}}$query_params->{'{{keyParamName}}'} = $self->get_api_key_with_prefix('{{keyParamName}}');{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}$header_params->{'Authorization'} = 'Basic '.encode_base64($WWW::{{invokerPackage}}::Configuration::username.":".$WWW::{{invokerPackage}}::Configuration::password);{{/isBasic}} + {{#isOAuth}}# TODO support oauth{{/isOAuth}} + } + {{/authMethods}} + else { + # TODO show warning about security definition not found + } + } +} + 1; diff --git a/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache b/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache index 90ad999c8a9..38eb2ad8dae 100644 --- a/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/Configuration.mustache @@ -12,5 +12,11 @@ our $api_client; our $http_timeout = 180; our $http_user_agent = 'Perl-Swagger'; +# authenticaiton setting +our $api_key = {}; +our $api_key_prefix = {}; +our $username; +our $password; + 1; diff --git a/modules/swagger-codegen/src/main/resources/perl/api.mustache b/modules/swagger-codegen/src/main/resources/perl/api.mustache index f1168d18ce7..5adb50344de 100644 --- a/modules/swagger-codegen/src/main/resources/perl/api.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/api.mustache @@ -116,18 +116,21 @@ sub new { $_body_data = $args{'{{paramName}}'}; }{{/bodyParams}} + # authentication setting, if any + my $auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}]; + # make the API Call {{#returnType}}my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); if (!$response) { return; } - my $_response_object = $self->{api_client}->deserialize('{{returnType}}', $response); - return $_response_object;{{/returnType}} + my $_response_object = $self->{api_client}->deserialize('{{returnType}}', $response); + return $_response_object;{{/returnType}} {{^returnType}}$self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; {{/returnType}} } diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm index c80677ca518..427c09324b8 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm @@ -4,6 +4,7 @@ use strict; use warnings; use utf8; +use MIME::Base64; use LWP::UserAgent; use HTTP::Headers; use HTTP::Response; @@ -61,9 +62,11 @@ sub set_timeout { # @return mixed sub call_api { my $self = shift; - my ($resource_path, $method, $query_params, $post_params, $header_params, $body_data) = @_; + my ($resource_path, $method, $query_params, $post_params, $header_params, $body_data, $auth_settings) = @_; + + # update parameters based on authentication settings + $self->update_params_for_auth($header_params, $query_params, $auth_settings); - my $headers = HTTP::Headers->new(%$header_params); my $_url = $self->{base_url} . $resource_path; @@ -72,38 +75,56 @@ sub call_api { $_url = ($_url . '?' . eval { URI::Query->new($query_params)->stringify }); } + # body data $body_data = to_json($body_data->to_hash) if defined $body_data && $body_data->can('to_hash'); # model to json string my $_body_data = %$post_params ? $post_params : $body_data; # Make the HTTP request my $_request; + use Data::Dumper; if ($method eq 'POST') { # multipart my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; + $header_params->{'Content-Type'} = $_content_type; + my $headers = HTTP::Headers->new(%$header_params); + + #$_request = POST($_url, Accept => $header_params->{Accept}, + # Content_Type => $_content_type, Content => $_body_data); + $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ); + print Dumper($_request); - $_request = POST($_url, Accept => $header_params->{Accept}, - Content_Type => $_content_type, Content => $_body_data); } elsif ($method eq 'PUT') { # multipart my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; - $_request = PUT($_url, Accept => $header_params->{Accept}, - Content_Type => $_content_type, Content => $_body_data); + $header_params->{'Content-Type'} = $_content_type; + my $headers = HTTP::Headers->new(%$header_params); + + #$_request = PUT($_url, Accept => $header_params->{Accept}, + # Content_Type => $_content_type, Content => $_body_data); + $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) + } elsif ($method eq 'GET') { - $_request = GET($_url, Accept => $header_params->{'Accept'}, - Content_Type => $header_params->{'Content-Type'}); + my $headers = HTTP::Headers->new(%$header_params); + #$_request = GET($_url, Accept => $header_params->{'Accept'}, + # Content_Type => $header_params->{'Content-Type'}); + $_request = HTTP::Request->new( $method, $_url, $headers) } elsif ($method eq 'HEAD') { - $_request = HEAD($_url, Accept => $header_params->{'Accept'}, - Content_Type => $header_params->{'Content-Type'}); + my $headers = HTTP::Headers->new(%$header_params); + #$_request = HEAD($_url, Accept => $header_params->{'Accept'}, + # Content_Type => $header_params->{'Content-Type'}); + $_request = HTTP::Request->new( $method, $_url, $headers) } elsif ($method eq 'DELETE') { #TODO support form data - $_request = DELETE($_url, Accept => $header_params->{'Accept'}, - Content_Type => $header_params->{'Content-Type'}, Content => $_body_data); + my $headers = HTTP::Headers->new(%$header_params); + #$_request = DELETE($_url, Accept => $header_params->{'Accept'}, + # Content_Type => $header_params->{'Content-Type'}, Content => $_body_data); + $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) } elsif ($method eq 'PATCH') { #TODO } @@ -256,5 +277,48 @@ sub select_header_content_type } +# Get API key (with prefix if set) +# @param string key name +# @return string API key with the prefix +sub get_api_key_with_prefix +{ + my ($self, $api_key) = @_; + if ($WWW::SwaggerClient::Configuration::api_key_prefix->{$api_key}) { + return $WWW::SwaggerClient::Configuration::api_key_prefix->{$api_key}." ".$WWW::SwaggerClient::Configuration::api_key->{$api_key}; + } else { + return $WWW::SwaggerClient::Configuration::api_key->{$api_key}; + } +} + +# update hearder and query param based on authentication setting +# +# @param array $headerParams header parameters (by ref) +# @param array $queryParams query parameters (by ref) +# @param array $authSettings array of authentication scheme (e.g ['api_key']) +sub update_params_for_auth { + my ($self, $header_params, $query_params, $auth_settings) = @_; + + return if (!defined($auth_settings) || scalar(@$auth_settings) == 0); + + # one endpoint can have more than 1 auth settings + foreach my $auth (@$auth_settings) { + # determine which one to use + if (!defined($auth)) { + } + elsif ($auth eq 'api_key') { + $header_params->{'api_key'} = $self->get_api_key_with_prefix('api_key'); + + } + elsif ($auth eq 'petstore_auth') { + + # TODO support oauth + } + + else { + # TODO show warning about security definition not found + } + } +} + 1; diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm index 08982c445e1..bbce9d74759 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/Configuration.pm @@ -12,5 +12,11 @@ our $api_client; our $http_timeout = 180; our $http_user_agent = 'Perl-Swagger'; +# authenticaiton setting +our $api_key = {}; +our $api_key_prefix = {}; +our $username; +our $password; + 1; diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm index 92fdd50e5ef..44bc1567a3d 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/PetApi.pm @@ -99,11 +99,14 @@ sub new { $_body_data = $args{'body'}; } + # authentication setting, if any + my $auth_settings = ['petstore_auth']; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } @@ -147,11 +150,14 @@ sub new { $_body_data = $args{'body'}; } + # authentication setting, if any + my $auth_settings = ['petstore_auth']; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } @@ -195,15 +201,18 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = ['petstore_auth']; + # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); if (!$response) { return; } - my $_response_object = $self->{api_client}->deserialize('ARRAY[Pet]', $response); - return $_response_object; + my $_response_object = $self->{api_client}->deserialize('ARRAY[Pet]', $response); + return $_response_object; } @@ -246,15 +255,18 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = ['petstore_auth']; + # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); if (!$response) { return; } - my $_response_object = $self->{api_client}->deserialize('ARRAY[Pet]', $response); - return $_response_object; + my $_response_object = $self->{api_client}->deserialize('ARRAY[Pet]', $response); + return $_response_object; } @@ -304,15 +316,18 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = ['api_key', 'petstore_auth']; + # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); if (!$response) { return; } - my $_response_object = $self->{api_client}->deserialize('Pet', $response); - return $_response_object; + my $_response_object = $self->{api_client}->deserialize('Pet', $response); + return $_response_object; } @@ -374,11 +389,14 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = ['petstore_auth']; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } @@ -433,11 +451,14 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = ['petstore_auth']; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } @@ -501,11 +522,14 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = ['petstore_auth']; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm index b6d864a6be3..6e22d4dbcc0 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/StoreApi.pm @@ -91,15 +91,18 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = ['api_key']; + # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); if (!$response) { return; } - my $_response_object = $self->{api_client}->deserialize('HASH[string,int]', $response); - return $_response_object; + my $_response_object = $self->{api_client}->deserialize('HASH[string,int]', $response); + return $_response_object; } @@ -142,15 +145,18 @@ sub new { $_body_data = $args{'body'}; } + # authentication setting, if any + my $auth_settings = []; + # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); if (!$response) { return; } - my $_response_object = $self->{api_client}->deserialize('Order', $response); - return $_response_object; + my $_response_object = $self->{api_client}->deserialize('Order', $response); + return $_response_object; } @@ -200,15 +206,18 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = []; + # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); if (!$response) { return; } - my $_response_object = $self->{api_client}->deserialize('Order', $response); - return $_response_object; + my $_response_object = $self->{api_client}->deserialize('Order', $response); + return $_response_object; } @@ -258,11 +267,14 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = []; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm index fa0d9ed5c4f..5b2fc0a0000 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/UserApi.pm @@ -99,11 +99,14 @@ sub new { $_body_data = $args{'body'}; } + # authentication setting, if any + my $auth_settings = []; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } @@ -147,11 +150,14 @@ sub new { $_body_data = $args{'body'}; } + # authentication setting, if any + my $auth_settings = []; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } @@ -195,11 +201,14 @@ sub new { $_body_data = $args{'body'}; } + # authentication setting, if any + my $auth_settings = []; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } @@ -247,15 +256,18 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = []; + # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); if (!$response) { return; } - my $_response_object = $self->{api_client}->deserialize('string', $response); - return $_response_object; + my $_response_object = $self->{api_client}->deserialize('string', $response); + return $_response_object; } @@ -294,11 +306,14 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = []; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } @@ -349,15 +364,18 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = []; + # make the API Call my $response = $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); if (!$response) { return; } - my $_response_object = $self->{api_client}->deserialize('User', $response); - return $_response_object; + my $_response_object = $self->{api_client}->deserialize('User', $response); + return $_response_object; } @@ -411,11 +429,14 @@ sub new { $_body_data = $args{'body'}; } + # authentication setting, if any + my $auth_settings = []; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } @@ -466,11 +487,14 @@ sub new { my $_body_data; + # authentication setting, if any + my $auth_settings = []; + # make the API Call $self->{api_client}->call_api($_resource_path, $_method, $query_params, $form_params, - $header_params, $_body_data); + $header_params, $_body_data, $auth_settings); return; } diff --git a/samples/client/petstore/perl/test.pl b/samples/client/petstore/perl/test.pl index 3479f6bd3a9..bce4da39adf 100755 --- a/samples/client/petstore/perl/test.pl +++ b/samples/client/petstore/perl/test.pl @@ -15,6 +15,8 @@ use Data::Dumper; use DateTime; $WWW::SwaggerClient::Configuration::http_user_agent = 'Perl-Swagger-Test'; +$WWW::SwaggerClient::Configuration::api_key->{'api_key'} = 'ZZZZZZZZZZZZZZ'; +$WWW::SwaggerClient::Configuration::api_key_prefix->{'api_key'} = 'BEARER'; my $api = WWW::SwaggerClient::PetApi->new(); From 9c747e3e37dea3e2b540c0413e6258a81a1a6731 Mon Sep 17 00:00:00 2001 From: wing328 Date: Wed, 3 Jun 2015 09:21:45 +0800 Subject: [PATCH 60/72] fix query parameters --- .../src/main/resources/csharp/ApiClient.mustache | 14 +++++++++++--- .../src/main/csharp/io/swagger/client/ApiClient.cs | 14 +++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache index c841efdc1b5..c5b72977cf5 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache @@ -53,7 +53,7 @@ namespace {{invokerPackage}} { // add query parameter, if any foreach(KeyValuePair param in QueryParams) - request.AddUrlSegment(param.Key, param.Value); + request.AddQueryParameter(param.Key, param.Value); // add form parameter, if any foreach(KeyValuePair param in FormParams) @@ -99,13 +99,21 @@ namespace {{invokerPackage}} { } /// - /// if parameter is DateTime, output in ISO8601 format, otherwise just return the string + /// if parameter is DateTime, output in ISO8601 format + /// if parameter is a list of string, join the list with "," + /// otherwise just return the string /// /// The parameter (header, path, query, form) /// Formatted string public string ParameterToString(object obj) { - return (obj is DateTime) ? ((DateTime)obj).ToString ("u") : Convert.ToString (obj); + if (obj is DateTime) { + return ((DateTime)obj).ToString ("u"); + } else if (obj is List) { + return String.Join(",", obj as List); + } else { + return Convert.ToString (obj); + } } /// diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs index c801bb1a736..39d59f063f2 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs @@ -53,7 +53,7 @@ namespace IO.Swagger.Client { // add query parameter, if any foreach(KeyValuePair param in QueryParams) - request.AddUrlSegment(param.Key, param.Value); + request.AddQueryParameter(param.Key, param.Value); // add form parameter, if any foreach(KeyValuePair param in FormParams) @@ -99,13 +99,21 @@ namespace IO.Swagger.Client { } /// - /// if parameter is DateTime, output in ISO8601 format, otherwise just return the string + /// if parameter is DateTime, output in ISO8601 format + /// if parameter is a list of string, join the list with "," + /// otherwise just return the string /// /// The parameter (header, path, query, form) /// Formatted string public string ParameterToString(object obj) { - return (obj is DateTime) ? ((DateTime)obj).ToString ("u") : Convert.ToString (obj); + if (obj is DateTime) { + return ((DateTime)obj).ToString ("u"); + } else if (obj is List) { + return String.Join(",", obj as List); + } else { + return Convert.ToString (obj); + } } /// From eb4973237ba6d0368c4346c9fe904ec7c1453114 Mon Sep 17 00:00:00 2001 From: xhh Date: Wed, 3 Jun 2015 10:09:36 +0800 Subject: [PATCH 61/72] Add comments to code --- .../main/resources/Java/ApiClient.mustache | 105 ++++++++++++++---- .../resources/Java/Configuration.mustache | 8 ++ .../main/resources/Java/apiException.mustache | 22 +--- .../java/io/swagger/client/ApiClient.java | 105 ++++++++++++++---- .../java/io/swagger/client/ApiException.java | 22 +--- .../java/io/swagger/client/Configuration.java | 8 ++ .../io/swagger/client/ConfigurationTest.java | 2 +- .../io/swagger/petstore/test/PetApiTest.java | 12 +- 8 files changed, 197 insertions(+), 87 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache index 45987bded75..ae79a726280 100644 --- a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache @@ -36,21 +36,18 @@ import java.text.ParseException; public class ApiClient { private Map hostMap = new HashMap(); private Map defaultHeaderMap = new HashMap(); - private boolean isDebug = false; + private boolean debugging = false; private String basePath = "{{basePath}}"; private DateFormat dateFormat; - private DateFormat datetimeFormat; public ApiClient() { // Use ISO 8601 format for date and datetime. // See https://en.wikipedia.org/wiki/ISO_8601 - this.dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - this.datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); // Use UTC as the default time zone. this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - this.datetimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); // Set default User-Agent. setUserAgent("Java-Swagger"); @@ -65,33 +62,60 @@ public class ApiClient { return this; } + /** + * Set the User-Agent header's value (by adding to the default header map). + */ public ApiClient setUserAgent(String userAgent) { addDefaultHeader("User-Agent", userAgent); return this; } + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + */ public ApiClient addDefaultHeader(String key, String value) { defaultHeaderMap.put(key, value); return this; } - public boolean isDebug() { - return isDebug; + /** + * Check that whether debugging is enabled for this API client. + */ + public boolean isDebugging() { + return debugging; } - public ApiClient enableDebug() { - isDebug = true; + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; return this; } - public Date parseDateTime(String str) { - try { - return datetimeFormat.parse(str); - } catch (java.text.ParseException e) { - throw new RuntimeException(e); - } + /** + * Get the date format used to parse/format date parameters. + */ + public DateFormat getDateFormat() { + return dateFormat; } + /** + * Set the date format used to parse/format date parameters. + */ + public ApiClient getDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + return this; + } + + /** + * Parse the given string into Date object. + */ public Date parseDate(String str) { try { return dateFormat.parse(str); @@ -100,19 +124,21 @@ public class ApiClient { } } - public String formatDateTime(Date datetime) { - return datetimeFormat.format(datetime); - } - + /** + * Format the given Date object into string. + */ public String formatDate(Date date) { return dateFormat.format(date); } + /** + * Format the given parameter object into string. + */ public String parameterToString(Object param) { if (param == null) { return ""; } else if (param instanceof Date) { - return formatDateTime((Date) param); + return formatDate((Date) param); } else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { @@ -127,15 +153,25 @@ public class ApiClient { } } + /** + * Escape the given string to be used as URL query value. + */ public String escapeString(String str) { - try{ + try { return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); - } - catch(UnsupportedEncodingException e) { + } catch (UnsupportedEncodingException e) { return str; } } + /** + * Deserialize the given JSON string to Java object. + * + * @param json The JSON string + * @param containerType The container type, one of "list", "array" or "" + * @param cls The type of the Java object + * @return The deserialized Java object + */ public Object deserialize(String json, String containerType, Class cls) throws ApiException { if(null != containerType) { containerType = containerType.toLowerCase(); @@ -161,6 +197,9 @@ public class ApiClient { } } + /** + * Serialize the given Java object into JSON string. + */ public String serialize(Object obj) throws ApiException { try { if (obj != null) @@ -173,6 +212,18 @@ public class ApiClient { } } + /** + * Invoke API by sending HTTP request with the given options. + * + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param contentType The request Content-Type + * @return The response body in type of string + */ public String invokeAPI(String path, String method, Map queryParams, Object body, Map headerParams, Map formParams, String contentType) throws ApiException { Client client = getClient(); @@ -278,6 +329,9 @@ public class ApiClient { } } + /** + * Encode the given form parameters as request body. + */ private String getXWWWFormUrlencodedParams(Map formParams) { StringBuilder formParamBuilder = new StringBuilder(); @@ -302,10 +356,13 @@ public class ApiClient { return encodedFormParams; } + /** + * Get an existing client or create a new client to handle HTTP request. + */ private Client getClient() { if(!hostMap.containsKey(basePath)) { Client client = Client.create(); - if(isDebug) + if (debugging) client.addFilter(new LoggingFilter()); hostMap.put(basePath, client); } diff --git a/modules/swagger-codegen/src/main/resources/Java/Configuration.mustache b/modules/swagger-codegen/src/main/resources/Java/Configuration.mustache index ce1e6dec1ce..9d7523d1fb3 100644 --- a/modules/swagger-codegen/src/main/resources/Java/Configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/Configuration.mustache @@ -3,10 +3,18 @@ package {{invokerPackage}}; public class Configuration { private static ApiClient defaultApiClient = new ApiClient(); + /** + * Get the default API client, which would be used when creating API + * instances without providing an API client. + */ public static ApiClient getDefaultApiClient() { return defaultApiClient; } + /** + * Set the default API client, which would be used when creating API + * instances without providing an API client. + */ public static void setDefaultApiClient(ApiClient apiClient) { defaultApiClient = apiClient; } diff --git a/modules/swagger-codegen/src/main/resources/Java/apiException.mustache b/modules/swagger-codegen/src/main/resources/Java/apiException.mustache index aac7caaf019..9afe96c6ffb 100644 --- a/modules/swagger-codegen/src/main/resources/Java/apiException.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/apiException.mustache @@ -27,31 +27,21 @@ public class ApiException extends Exception { return code; } - public void setCode(int code) { - this.code = code; - } - public String getMessage() { return message; } - public void setMessage(String message) { - this.message = message; - } - + /** + * Get the HTTP response headers. + */ public Map> getResponseHeaders() { return responseHeaders; } - public void setResponseHeaders(Map> responseHeaders) { - this.responseHeaders = responseHeaders; - } - + /** + * Get the HTTP response body. + */ public String getResponseBody() { return responseBody; } - - public void setResponseBody(String responseBody) { - this.responseBody = responseBody; - } } diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java index 6a4dfffefab..38f021aab22 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java @@ -36,21 +36,18 @@ import java.text.ParseException; public class ApiClient { private Map hostMap = new HashMap(); private Map defaultHeaderMap = new HashMap(); - private boolean isDebug = false; + private boolean debugging = false; private String basePath = "http://petstore.swagger.io/v2"; private DateFormat dateFormat; - private DateFormat datetimeFormat; public ApiClient() { // Use ISO 8601 format for date and datetime. // See https://en.wikipedia.org/wiki/ISO_8601 - this.dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - this.datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); // Use UTC as the default time zone. this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - this.datetimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); // Set default User-Agent. setUserAgent("Java-Swagger"); @@ -65,33 +62,60 @@ public class ApiClient { return this; } + /** + * Set the User-Agent header's value (by adding to the default header map). + */ public ApiClient setUserAgent(String userAgent) { addDefaultHeader("User-Agent", userAgent); return this; } + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + */ public ApiClient addDefaultHeader(String key, String value) { defaultHeaderMap.put(key, value); return this; } - public boolean isDebug() { - return isDebug; + /** + * Check that whether debugging is enabled for this API client. + */ + public boolean isDebugging() { + return debugging; } - public ApiClient enableDebug() { - isDebug = true; + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; return this; } - public Date parseDateTime(String str) { - try { - return datetimeFormat.parse(str); - } catch (java.text.ParseException e) { - throw new RuntimeException(e); - } + /** + * Get the date format used to parse/format date parameters. + */ + public DateFormat getDateFormat() { + return dateFormat; } + /** + * Set the date format used to parse/format date parameters. + */ + public ApiClient getDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + return this; + } + + /** + * Parse the given string into Date object. + */ public Date parseDate(String str) { try { return dateFormat.parse(str); @@ -100,19 +124,21 @@ public class ApiClient { } } - public String formatDateTime(Date datetime) { - return datetimeFormat.format(datetime); - } - + /** + * Format the given Date object into string. + */ public String formatDate(Date date) { return dateFormat.format(date); } + /** + * Format the given parameter object into string. + */ public String parameterToString(Object param) { if (param == null) { return ""; } else if (param instanceof Date) { - return formatDateTime((Date) param); + return formatDate((Date) param); } else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { @@ -127,15 +153,25 @@ public class ApiClient { } } + /** + * Escape the given string to be used as URL query value. + */ public String escapeString(String str) { - try{ + try { return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); - } - catch(UnsupportedEncodingException e) { + } catch (UnsupportedEncodingException e) { return str; } } + /** + * Deserialize the given JSON string to Java object. + * + * @param json The JSON string + * @param containerType The container type, one of "list", "array" or "" + * @param cls The type of the Java object + * @return The deserialized Java object + */ public Object deserialize(String json, String containerType, Class cls) throws ApiException { if(null != containerType) { containerType = containerType.toLowerCase(); @@ -161,6 +197,9 @@ public class ApiClient { } } + /** + * Serialize the given Java object into JSON string. + */ public String serialize(Object obj) throws ApiException { try { if (obj != null) @@ -173,6 +212,18 @@ public class ApiClient { } } + /** + * Invoke API by sending HTTP request with the given options. + * + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param contentType The request Content-Type + * @return The response body in type of string + */ public String invokeAPI(String path, String method, Map queryParams, Object body, Map headerParams, Map formParams, String contentType) throws ApiException { Client client = getClient(); @@ -278,6 +329,9 @@ public class ApiClient { } } + /** + * Encode the given form parameters as request body. + */ private String getXWWWFormUrlencodedParams(Map formParams) { StringBuilder formParamBuilder = new StringBuilder(); @@ -302,10 +356,13 @@ public class ApiClient { return encodedFormParams; } + /** + * Get an existing client or create a new client to handle HTTP request. + */ private Client getClient() { if(!hostMap.containsKey(basePath)) { Client client = Client.create(); - if(isDebug) + if (debugging) client.addFilter(new LoggingFilter()); hostMap.put(basePath, client); } diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiException.java b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiException.java index 515c21d85d4..a39785eb47e 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiException.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiException.java @@ -27,31 +27,21 @@ public class ApiException extends Exception { return code; } - public void setCode(int code) { - this.code = code; - } - public String getMessage() { return message; } - public void setMessage(String message) { - this.message = message; - } - + /** + * Get the HTTP response headers. + */ public Map> getResponseHeaders() { return responseHeaders; } - public void setResponseHeaders(Map> responseHeaders) { - this.responseHeaders = responseHeaders; - } - + /** + * Get the HTTP response body. + */ public String getResponseBody() { return responseBody; } - - public void setResponseBody(String responseBody) { - this.responseBody = responseBody; - } } diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java b/samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java index 63622ead5dc..f7c360d6122 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java @@ -3,10 +3,18 @@ package io.swagger.client; public class Configuration { private static ApiClient defaultApiClient = new ApiClient(); + /** + * Get the default API client, which would be used when creating API + * instances without providing an API client. + */ public static ApiClient getDefaultApiClient() { return defaultApiClient; } + /** + * Set the default API client, which would be used when creating API + * instances without providing an API client. + */ public static void setDefaultApiClient(ApiClient apiClient) { defaultApiClient = apiClient; } diff --git a/samples/client/petstore/java/src/test/java/io/swagger/client/ConfigurationTest.java b/samples/client/petstore/java/src/test/java/io/swagger/client/ConfigurationTest.java index e16eaf4c086..9801be416fb 100644 --- a/samples/client/petstore/java/src/test/java/io/swagger/client/ConfigurationTest.java +++ b/samples/client/petstore/java/src/test/java/io/swagger/client/ConfigurationTest.java @@ -9,6 +9,6 @@ public class ConfigurationTest { ApiClient apiClient = Configuration.getDefaultApiClient(); assertNotNull(apiClient); assertEquals("http://petstore.swagger.io/v2", apiClient.getBasePath()); - assertFalse(apiClient.isDebug()); + assertFalse(apiClient.isDebugging()); } } diff --git a/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java b/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java index 8416e13b468..4ea5474eb59 100644 --- a/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java +++ b/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java @@ -26,25 +26,25 @@ public class PetApiTest { assertEquals(Configuration.getDefaultApiClient(), api.getApiClient()); assertNotNull(api.getApiClient()); assertEquals("http://petstore.swagger.io/v2", api.getApiClient().getBasePath()); - assertFalse(api.getApiClient().isDebug()); + assertFalse(api.getApiClient().isDebugging()); ApiClient oldClient = api.getApiClient(); ApiClient newClient = new ApiClient(); newClient.setBasePath("http://example.com"); - newClient.enableDebug(); + newClient.setDebugging(true); // set api client via constructor api = new PetApi(newClient); assertNotNull(api.getApiClient()); assertEquals("http://example.com", api.getApiClient().getBasePath()); - assertTrue(api.getApiClient().isDebug()); + assertTrue(api.getApiClient().isDebugging()); // set api client via setter method api.setApiClient(oldClient); assertNotNull(api.getApiClient()); assertEquals("http://petstore.swagger.io/v2", api.getApiClient().getBasePath()); - assertFalse(api.getApiClient().isDebug()); + assertFalse(api.getApiClient().isDebugging()); } @Test @@ -129,7 +129,7 @@ public class PetApiTest { api.addPet(pet); Pet fetched = api.getPetById(pet.getId()); - + api.updatePetWithForm(String.valueOf(fetched.getId()), "furt", null); Pet updated = api.getPetById(fetched.getId()); @@ -181,4 +181,4 @@ public class PetApiTest { return pet; } -} \ No newline at end of file +} From fceaed34e47573c3fbaa9cb7dfe5180a3caa04cd Mon Sep 17 00:00:00 2001 From: wing328 Date: Wed, 3 Jun 2015 10:19:07 +0800 Subject: [PATCH 62/72] rename apiclient --- .../client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm index 427c09324b8..c9e9d82df10 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm @@ -82,7 +82,6 @@ sub call_api { # Make the HTTP request my $_request; - use Data::Dumper; if ($method eq 'POST') { # multipart my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? @@ -92,8 +91,7 @@ sub call_api { #$_request = POST($_url, Accept => $header_params->{Accept}, # Content_Type => $_content_type, Content => $_body_data); - $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ); - print Dumper($_request); + $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) } elsif ($method eq 'PUT') { From 9b919c54dde59711a1378c836940832ebe77dabb Mon Sep 17 00:00:00 2001 From: wing328 Date: Wed, 3 Jun 2015 11:21:10 +0800 Subject: [PATCH 63/72] added http basic auth test --- .../main/resources/perl/APIClient.mustache | 28 +++++-------------- .../perl/lib/WWW/SwaggerClient/APIClient.pm | 28 +++++-------------- samples/client/petstore/perl/test.pl | 4 +++ 3 files changed, 18 insertions(+), 42 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache index 2b0f39a41cd..1d71ca3f99a 100644 --- a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache @@ -84,45 +84,31 @@ sub call_api { my $_request; if ($method eq 'POST') { # multipart - my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? + $header_params->{'Content-Type'} = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; - $header_params->{'Content-Type'} = $_content_type; - my $headers = HTTP::Headers->new(%$header_params); - #$_request = POST($_url, Accept => $header_params->{Accept}, - # Content_Type => $_content_type, Content => $_body_data); - $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) + $_request = POST($_url, %$header_params, Content => $_body_data); } elsif ($method eq 'PUT') { # multipart - my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? + $header_params->{'Content-Type'} = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; - $header_params->{'Content-Type'} = $_content_type; - my $headers = HTTP::Headers->new(%$header_params); - #$_request = PUT($_url, Accept => $header_params->{Accept}, - # Content_Type => $_content_type, Content => $_body_data); - $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) + $_request = PUT($_url, %$header_params, Content => $_body_data); } elsif ($method eq 'GET') { my $headers = HTTP::Headers->new(%$header_params); - #$_request = GET($_url, Accept => $header_params->{'Accept'}, - # Content_Type => $header_params->{'Content-Type'}); - $_request = HTTP::Request->new( $method, $_url, $headers) + $_request = GET($_url, %$header_params); } elsif ($method eq 'HEAD') { my $headers = HTTP::Headers->new(%$header_params); - #$_request = HEAD($_url, Accept => $header_params->{'Accept'}, - # Content_Type => $header_params->{'Content-Type'}); - $_request = HTTP::Request->new( $method, $_url, $headers) + $_request = HEAD($_url,%$header_params); } elsif ($method eq 'DELETE') { #TODO support form data my $headers = HTTP::Headers->new(%$header_params); - #$_request = DELETE($_url, Accept => $header_params->{'Accept'}, - # Content_Type => $header_params->{'Content-Type'}, Content => $_body_data); - $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) + $_request = DELETE($_url, %$headers); } elsif ($method eq 'PATCH') { #TODO } diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm index c9e9d82df10..0ac34355c4c 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm @@ -84,45 +84,31 @@ sub call_api { my $_request; if ($method eq 'POST') { # multipart - my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? + $header_params->{'Content-Type'} = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; - $header_params->{'Content-Type'} = $_content_type; - my $headers = HTTP::Headers->new(%$header_params); - #$_request = POST($_url, Accept => $header_params->{Accept}, - # Content_Type => $_content_type, Content => $_body_data); - $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) + $_request = POST($_url, %$header_params, Content => $_body_data); } elsif ($method eq 'PUT') { # multipart - my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? + $header_params->{'Content-Type'} = lc $header_params->{'Content-Type'} eq 'multipart/form' ? 'form-data' : $header_params->{'Content-Type'}; - $header_params->{'Content-Type'} = $_content_type; - my $headers = HTTP::Headers->new(%$header_params); - #$_request = PUT($_url, Accept => $header_params->{Accept}, - # Content_Type => $_content_type, Content => $_body_data); - $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) + $_request = PUT($_url, %$header_params, Content => $_body_data); } elsif ($method eq 'GET') { my $headers = HTTP::Headers->new(%$header_params); - #$_request = GET($_url, Accept => $header_params->{'Accept'}, - # Content_Type => $header_params->{'Content-Type'}); - $_request = HTTP::Request->new( $method, $_url, $headers) + $_request = GET($_url, %$header_params); } elsif ($method eq 'HEAD') { my $headers = HTTP::Headers->new(%$header_params); - #$_request = HEAD($_url, Accept => $header_params->{'Accept'}, - # Content_Type => $header_params->{'Content-Type'}); - $_request = HTTP::Request->new( $method, $_url, $headers) + $_request = HEAD($_url,%$header_params); } elsif ($method eq 'DELETE') { #TODO support form data my $headers = HTTP::Headers->new(%$header_params); - #$_request = DELETE($_url, Accept => $header_params->{'Accept'}, - # Content_Type => $header_params->{'Content-Type'}, Content => $_body_data); - $_request = HTTP::Request->new( $method, $_url, $headers, $_body_data ) + $_request = DELETE($_url, %$headers); } elsif ($method eq 'PATCH') { #TODO } diff --git a/samples/client/petstore/perl/test.pl b/samples/client/petstore/perl/test.pl index bce4da39adf..d4f3fbb6f4b 100755 --- a/samples/client/petstore/perl/test.pl +++ b/samples/client/petstore/perl/test.pl @@ -18,6 +18,10 @@ $WWW::SwaggerClient::Configuration::http_user_agent = 'Perl-Swagger-Test'; $WWW::SwaggerClient::Configuration::api_key->{'api_key'} = 'ZZZZZZZZZZZZZZ'; $WWW::SwaggerClient::Configuration::api_key_prefix->{'api_key'} = 'BEARER'; +$WWW::SwaggerClient::Configuration::username = 'username'; +$WWW::SwaggerClient::Configuration::password = 'password'; + + my $api = WWW::SwaggerClient::PetApi->new(); my $pet_id = 10008; From 2e285ed5622d9476bd02109e545ca274fa0148e9 Mon Sep 17 00:00:00 2001 From: xhh Date: Wed, 3 Jun 2015 12:49:09 +0800 Subject: [PATCH 64/72] Support skipping SSL certification verification in Ruby clients by e.g.: SwaggerClient::Swagger.configure do |config| config.verify_ssl = false end --- .../ruby/swagger/configuration.mustache | 10 +++++++++- .../resources/ruby/swagger/request.mustache | 19 ++++++++++--------- .../swagger_client/swagger/configuration.rb | 10 +++++++++- .../lib/swagger_client/swagger/request.rb | 19 ++++++++++--------- 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/ruby/swagger/configuration.mustache b/modules/swagger-codegen/src/main/resources/ruby/swagger/configuration.mustache index e6479797920..e9a8af9c162 100644 --- a/modules/swagger-codegen/src/main/resources/ruby/swagger/configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/ruby/swagger/configuration.mustache @@ -1,7 +1,7 @@ module {{moduleName}} module Swagger class Configuration - attr_accessor :format, :api_key, :api_key_prefix, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent + attr_accessor :format, :api_key, :api_key_prefix, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent, :verify_ssl # Defaults go in here.. def initialize @@ -13,8 +13,16 @@ module {{moduleName}} @inject_format = false @force_ending_format = false @camelize_params = true + + # keys for API key authentication (param-name => api-key) @api_key = {} + # api-key prefix for API key authentication, e.g. "Bearer" (param-name => api-key-prefix) @api_key_prefix = {} + + # whether to verify SSL certificate, default to true + # Note: do NOT set it to false in production code, otherwise you would + # face multiple types of cryptographic attacks + @verify_ssl = true end end end diff --git a/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache b/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache index 85270369763..3c6aa31df4e 100644 --- a/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache +++ b/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache @@ -160,39 +160,40 @@ module {{moduleName}} #TODO use configuration setting to determine if debugging #logger = Logger.new STDOUT #logger.debug self.url + + request_options = { + :ssl_verifypeer => Swagger.configuration.verify_ssl, + :headers => self.headers.stringify_keys + } response = case self.http_method.to_sym when :get,:GET Typhoeus::Request.get( self.url, - :headers => self.headers.stringify_keys, + request_options ) when :post,:POST Typhoeus::Request.post( self.url, - :body => self.outgoing_body, - :headers => self.headers.stringify_keys, + request_options.merge(:body => self.outgoing_body) ) when :patch,:PATCH Typhoeus::Request.patch( self.url, - :body => self.outgoing_body, - :headers => self.headers.stringify_keys, + request_options.merge(:body => self.outgoing_body) ) when :put,:PUT Typhoeus::Request.put( self.url, - :body => self.outgoing_body, - :headers => self.headers.stringify_keys, + request_options.merge(:body => self.outgoing_body) ) when :delete,:DELETE Typhoeus::Request.delete( self.url, - :body => self.outgoing_body, - :headers => self.headers.stringify_keys, + request_options.merge(:body => self.outgoing_body) ) end Response.new(response) diff --git a/samples/client/petstore/ruby/lib/swagger_client/swagger/configuration.rb b/samples/client/petstore/ruby/lib/swagger_client/swagger/configuration.rb index 91cdb66e099..a2d4fe0e291 100644 --- a/samples/client/petstore/ruby/lib/swagger_client/swagger/configuration.rb +++ b/samples/client/petstore/ruby/lib/swagger_client/swagger/configuration.rb @@ -1,7 +1,7 @@ module SwaggerClient module Swagger class Configuration - attr_accessor :format, :api_key, :api_key_prefix, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent + attr_accessor :format, :api_key, :api_key_prefix, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent, :verify_ssl # Defaults go in here.. def initialize @@ -13,8 +13,16 @@ module SwaggerClient @inject_format = false @force_ending_format = false @camelize_params = true + + # keys for API key authentication (param-name => api-key) @api_key = {} + # api-key prefix for API key authentication, e.g. "Bearer" (param-name => api-key-prefix) @api_key_prefix = {} + + # whether to verify SSL certificate, default to true + # Note: do NOT set it to false in production code, otherwise you would + # face multiple types of cryptographic attacks + @verify_ssl = true end end end diff --git a/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb b/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb index a595d6ab7a1..fea2ea2a5cd 100644 --- a/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb +++ b/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb @@ -159,39 +159,40 @@ module SwaggerClient #TODO use configuration setting to determine if debugging #logger = Logger.new STDOUT #logger.debug self.url + + request_options = { + :ssl_verifypeer => Swagger.configuration.verify_ssl, + :headers => self.headers.stringify_keys + } response = case self.http_method.to_sym when :get,:GET Typhoeus::Request.get( self.url, - :headers => self.headers.stringify_keys, + request_options ) when :post,:POST Typhoeus::Request.post( self.url, - :body => self.outgoing_body, - :headers => self.headers.stringify_keys, + request_options.merge(:body => self.outgoing_body) ) when :patch,:PATCH Typhoeus::Request.patch( self.url, - :body => self.outgoing_body, - :headers => self.headers.stringify_keys, + request_options.merge(:body => self.outgoing_body) ) when :put,:PUT Typhoeus::Request.put( self.url, - :body => self.outgoing_body, - :headers => self.headers.stringify_keys, + request_options.merge(:body => self.outgoing_body) ) when :delete,:DELETE Typhoeus::Request.delete( self.url, - :body => self.outgoing_body, - :headers => self.headers.stringify_keys, + request_options.merge(:body => self.outgoing_body) ) end Response.new(response) From cf4b4de970c16cdb25b5516f8ce374a3a40eaf54 Mon Sep 17 00:00:00 2001 From: xhh Date: Wed, 3 Jun 2015 20:26:14 +0800 Subject: [PATCH 65/72] Skip null header/form parameters and fix the bug of getting file name for file parameter --- .../src/main/resources/Java/api.mustache | 20 ++++++---- .../java/io/swagger/client/api/PetApi.java | 38 ++++++++++++------- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/Java/api.mustache b/modules/swagger-codegen/src/main/resources/Java/api.mustache index 6e6a7a79940..b33fd7f3733 100644 --- a/modules/swagger-codegen/src/main/resources/Java/api.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/api.mustache @@ -68,7 +68,8 @@ public class {{classname}} { {{#queryParams}}if ({{paramName}} != null) queryParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/queryParams}} - {{#headerParams}}headerParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{#headerParams}}if ({{paramName}} != null) + headerParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/headerParams}} String[] contentTypes = { {{#consumes}}"{{mediaType}}"{{#hasMore}},{{/hasMore}}{{/consumes}} @@ -80,18 +81,23 @@ public class {{classname}} { boolean hasFields = false; FormDataMultiPart mp = new FormDataMultiPart(); {{#formParams}}{{#notFile}} - hasFields = true; - mp.field("{{baseName}}", apiClient.parameterToString({{paramName}}), MediaType.MULTIPART_FORM_DATA_TYPE); + if ({{paramName}} != null) { + hasFields = true; + mp.field("{{baseName}}", apiClient.parameterToString({{paramName}}), MediaType.MULTIPART_FORM_DATA_TYPE); + } {{/notFile}}{{#isFile}} - hasFields = true; - mp.field("{{baseName}}", file.getName()); - mp.bodyPart(new FileDataBodyPart("{{baseName}}", {{paramName}}, MediaType.MULTIPART_FORM_DATA_TYPE)); + if ({{paramName}} != null) { + hasFields = true; + mp.field("{{baseName}}", {{paramName}}.getName()); + mp.bodyPart(new FileDataBodyPart("{{baseName}}", {{paramName}}, MediaType.MULTIPART_FORM_DATA_TYPE)); + } {{/isFile}}{{/formParams}} if(hasFields) postBody = mp; } else { - {{#formParams}}{{#notFile}}formParams.put("{{baseName}}", apiClient.parameterToString({{paramName}}));{{/notFile}} + {{#formParams}}{{#notFile}}if ({{paramName}} != null) + formParams.put("{{baseName}}", apiClient.parameterToString({{paramName}}));{{/notFile}} {{/formParams}} } diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java b/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java index 4d3d5c51d87..1c3cc4cb483 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java @@ -338,18 +338,24 @@ public class PetApi { boolean hasFields = false; FormDataMultiPart mp = new FormDataMultiPart(); - hasFields = true; - mp.field("name", apiClient.parameterToString(name), MediaType.MULTIPART_FORM_DATA_TYPE); + if (name != null) { + hasFields = true; + mp.field("name", apiClient.parameterToString(name), MediaType.MULTIPART_FORM_DATA_TYPE); + } - hasFields = true; - mp.field("status", apiClient.parameterToString(status), MediaType.MULTIPART_FORM_DATA_TYPE); + if (status != null) { + hasFields = true; + mp.field("status", apiClient.parameterToString(status), MediaType.MULTIPART_FORM_DATA_TYPE); + } if(hasFields) postBody = mp; } else { - formParams.put("name", apiClient.parameterToString(name)); - formParams.put("status", apiClient.parameterToString(status)); + if (name != null) + formParams.put("name", apiClient.parameterToString(name)); + if (status != null) + formParams.put("status", apiClient.parameterToString(status)); } @@ -392,7 +398,8 @@ public class PetApi { Map formParams = new HashMap(); - headerParams.put("api_key", apiClient.parameterToString(apiKey)); + if (apiKey != null) + headerParams.put("api_key", apiClient.parameterToString(apiKey)); String[] contentTypes = { @@ -462,18 +469,23 @@ public class PetApi { boolean hasFields = false; FormDataMultiPart mp = new FormDataMultiPart(); - hasFields = true; - mp.field("additionalMetadata", apiClient.parameterToString(additionalMetadata), MediaType.MULTIPART_FORM_DATA_TYPE); + if (additionalMetadata != null) { + hasFields = true; + mp.field("additionalMetadata", apiClient.parameterToString(additionalMetadata), MediaType.MULTIPART_FORM_DATA_TYPE); + } - hasFields = true; - mp.field("file", file.getName()); - mp.bodyPart(new FileDataBodyPart("file", file, MediaType.MULTIPART_FORM_DATA_TYPE)); + if (file != null) { + hasFields = true; + mp.field("file", file.getName()); + mp.bodyPart(new FileDataBodyPart("file", file, MediaType.MULTIPART_FORM_DATA_TYPE)); + } if(hasFields) postBody = mp; } else { - formParams.put("additionalMetadata", apiClient.parameterToString(additionalMetadata)); + if (additionalMetadata != null) + formParams.put("additionalMetadata", apiClient.parameterToString(additionalMetadata)); } From 0ffe53933df28281ea844fc86a3654bff7dd87db Mon Sep 17 00:00:00 2001 From: xhh Date: Wed, 3 Jun 2015 21:17:42 +0800 Subject: [PATCH 66/72] Bug fix: "null" was used as post body for empty form parameters The form parameters could be empty when all of them are optional and no values are assigned to them. --- .../src/main/resources/ruby/swagger/request.mustache | 6 ++++-- .../petstore/ruby/lib/swagger_client/swagger/request.rb | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache b/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache index 3c6aa31df4e..99b58d58be8 100644 --- a/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache +++ b/modules/swagger-codegen/src/main/resources/ruby/swagger/request.mustache @@ -120,14 +120,16 @@ module {{moduleName}} # For form parameters, remove empty value def outgoing_body # http form - if @body.nil? && @form_params && !@form_params.empty? + if headers['Content-Type'] == 'application/x-www-form-urlencoded' data = form_params.dup data.each do |key, value| data[key] = value.to_s if value && !value.is_a?(File) # remove emtpy form parameter end data - else # http body is JSON + elsif @body # http body is JSON @body.is_a?(String) ? @body : @body.to_json + else + nil end end diff --git a/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb b/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb index fea2ea2a5cd..4cd5d84b0b9 100644 --- a/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb +++ b/samples/client/petstore/ruby/lib/swagger_client/swagger/request.rb @@ -119,14 +119,16 @@ module SwaggerClient # For form parameters, remove empty value def outgoing_body # http form - if @body.nil? && @form_params && !@form_params.empty? + if headers['Content-Type'] == 'application/x-www-form-urlencoded' data = form_params.dup data.each do |key, value| data[key] = value.to_s if value && !value.is_a?(File) # remove emtpy form parameter end data - else # http body is JSON + elsif @body # http body is JSON @body.is_a?(String) ? @body : @body.to_json + else + nil end end From 58feda7c8e075d6f41f003ee86aaf42bfd80b004 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Thu, 4 Jun 2015 16:44:12 +0800 Subject: [PATCH 67/72] Updated test case `testCreateAndGetPet` of objc client. --- .../PetstoreClientTests/PetApiTest.m | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m b/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m index 6fb2b6e57c2..32625dce467 100644 --- a/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m @@ -27,6 +27,24 @@ } if(output){ XCTAssertNotNil([output _id], @"token was nil"); + + // test category of pet is correct + XCTAssertEqualObjects(output.category._id, pet.category._id); + XCTAssertEqualObjects(output.category.name, pet.category.name); + + // test tags of pet is correct + XCTAssertTrue([output.tags isKindOfClass:[NSArray class]]); + [pet.tags enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + SWGTag *foundTag = [[SWGTag alloc] init]; + for (SWGTag *tag in output.tags) { + if ([tag _id] == [obj _id]) { + foundTag = tag; + } + } + XCTAssertNotNil(foundTag); + XCTAssertEqualObjects([foundTag _id], [obj _id]); + XCTAssertEqualObjects([foundTag name], [obj name]); + }]; } [expectation fulfill]; }]; @@ -221,10 +239,20 @@ SWGPet * pet = [[SWGPet alloc] init]; pet._id = [[NSNumber alloc] initWithLong:[[NSDate date] timeIntervalSince1970]]; pet.name = @"monkey"; + SWGCategory * category = [[SWGCategory alloc] init]; + category._id = [[NSNumber alloc] initWithInteger:arc4random_uniform(100000)]; category.name = @"super-happy"; - pet.category = category; + + SWGTag *tag1 = [[SWGTag alloc] init]; + tag1._id = [[NSNumber alloc] initWithInteger:arc4random_uniform(100000)]; + tag1.name = @"test tag 1"; + SWGTag *tag2 = [[SWGTag alloc] init]; + tag2._id = [[NSNumber alloc] initWithInteger:arc4random_uniform(100000)]; + tag2.name = @"test tag 2"; + pet.tags = (NSArray *)[[NSArray alloc] initWithObjects:tag1, tag2, nil]; + pet.status = @"available"; NSArray * photos = [[NSArray alloc] initWithObjects:@"http://foo.bar.com/3", @"http://foo.bar.com/4", nil]; From afe816efb6019cc9f7d47fc51bb73836de014423 Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 4 Jun 2015 20:30:41 +0800 Subject: [PATCH 68/72] remove unused file --- :w | 290 ------------------------------------------------------------- 1 file changed, 290 deletions(-) delete mode 100644 :w diff --git a/:w b/:w deleted file mode 100644 index b34a3de344b..00000000000 --- a/:w +++ /dev/null @@ -1,290 +0,0 @@ -package WWW::{{invokerPackage}}::ApiClient; - -use strict; -use warnings; -use utf8; - -use MIME::Base64; -use LWP::UserAgent; -use HTTP::Headers; -use HTTP::Response; -use HTTP::Request::Common qw(DELETE POST GET HEAD PUT); -use HTTP::Status; -use URI::Query; -use JSON; -use URI::Escape; -use Scalar::Util; -use Log::Any qw($log); -use Carp; -use Module::Runtime qw(use_module); - -use WWW::{{invokerPackage}}::Configuration; - -sub new -{ - my $class = shift; - my (%args) = ( - 'ua' => LWP::UserAgent->new, - 'base_url' => '{{basePath}}', - @_ - ); - - return bless \%args, $class; -} - -# Set the user agent of the API client -# -# @param string $user_agent The user agent of the API client -# -sub set_user_agent { - my ($self, $user_agent) = @_; - $self->{http_user_agent}= $user_agent; -} - -# Set timeout -# -# @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] -# -sub set_timeout { - my ($self, $seconds) = @_; - if (!looks_like_number($seconds)) { - croak('Timeout variable must be numeric.'); - } - $self->{http_timeout} = $seconds; -} - -# make the HTTP request -# @param string $resourcePath path to method endpoint -# @param string $method method to call -# @param array $queryParams parameters to be place in query URL -# @param array $postData parameters to be placed in POST body -# @param array $headerParams parameters to be place in request header -# @return mixed -sub call_api { - my $self = shift; - my ($resource_path, $method, $query_params, $post_params, $header_params, $body_data, $auth_settings) = @_; - - my $headers = HTTP::Headers->new(%$header_params); - - my $_url = $self->{base_url} . $resource_path; - - # build query - if (%$query_params) { - $_url = ($_url . '?' . eval { URI::Query->new($query_params)->stringify }); - } - - # update parameters based on authentication settings - update_params_for_auth(\$query_params, \$header_params, \$auth_settings); - - # body data - $body_data = to_json($body_data->to_hash) if defined $body_data && $body_data->can('to_hash'); # model to json string - my $_body_data = %$post_params ? $post_params : $body_data; - - # Make the HTTP request - my $_request; - if ($method eq 'POST') { - # multipart - my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? - 'form-data' : $header_params->{'Content-Type'}; - - $_request = POST($_url, Accept => $header_params->{Accept}, - Content_Type => $_content_type, Content => $_body_data); - } - elsif ($method eq 'PUT') { - # multipart - my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ? - 'form-data' : $header_params->{'Content-Type'}; - $_request = PUT($_url, Accept => $header_params->{Accept}, - Content_Type => $_content_type, Content => $_body_data); - } - elsif ($method eq 'GET') { - $_request = GET($_url, Accept => $header_params->{'Accept'}, - Content_Type => $header_params->{'Content-Type'}); - } - elsif ($method eq 'HEAD') { - $_request = HEAD($_url, Accept => $header_params->{'Accept'}, - Content_Type => $header_params->{'Content-Type'}); - } - elsif ($method eq 'DELETE') { #TODO support form data - $_request = DELETE($_url, Accept => $header_params->{'Accept'}, - Content_Type => $header_params->{'Content-Type'}, Content => $_body_data); - } - elsif ($method eq 'PATCH') { #TODO - } - else { - } - - $self->{ua}->timeout($self->{http_timeout} || $WWW::{{invokerPackage}}::Configuration::http_timeout); - $self->{ua}->agent($self->{http_user_agent} || $WWW::{{invokerPackage}}::Configuration::http_user_agent); - - my $_response = $self->{ua}->request($_request); - - unless ($_response->is_success) { - croak("API Exception(".$_response->code."): ".$_response->message); - } - - return $_response->content; - -} - -# Take value and turn it into a string suitable for inclusion in -# the path, by url-encoding. -# @param string $value a string which will be part of the path -# @return string the serialized object -sub to_path_value { - my ($self, $value) = @_; - return uri_escape($self->to_string($value)); -} - - -# Take value and turn it into a string suitable for inclusion in -# the query, by imploding comma-separated if it's an object. -# If it's a string, pass through unchanged. It will be url-encoded -# later. -# @param object $object an object to be serialized to a string -# @return string the serialized object -sub to_query_value { - my ($self, $object) = @_; - if (is_array($object)) { - return implode(',', $object); - } else { - return $self->to_string($object); - } -} - - -# Take value and turn it into a string suitable for inclusion in -# the header. If it's a string, pass through unchanged -# If it's a datetime object, format it in ISO8601 -# @param string $value a string which will be part of the header -# @return string the header string -sub to_header_value { - my ($self, $value) = @_; - return $self->to_string($value); -} - -# Take value and turn it into a string suitable for inclusion in -# the http body (form parameter). If it's a string, pass through unchanged -# If it's a datetime object, format it in ISO8601 -# @param string $value the value of the form parameter -# @return string the form string -sub to_form_value { - my ($self, $value) = @_; - return $self->to_string($value); -} - -# Take value and turn it into a string suitable for inclusion in -# the parameter. If it's a string, pass through unchanged -# If it's a datetime object, format it in ISO8601 -# @param string $value the value of the parameter -# @return string the header string -sub to_string { - my ($self, $value) = @_; - if (ref($value) eq "DateTime") { # datetime in ISO8601 format - return $value->datetime(); - } - else { - return $value; - } -} - -# Deserialize a JSON string into an object -# -# @param string $class class name is passed as a string -# @param string $data data of the body -# @return object an instance of $class -sub deserialize -{ - my ($self, $class, $data) = @_; - $log->debugf("deserializing %s for %s", $data, $class); - my $_result; - - if (not defined $data) { - return undef; - } elsif ( lc(substr($class, 0, 4)) eq 'map[') { #hash - $_result = \(json_decode $data); - } elsif ( lc(substr($class, 0, 6)) eq 'array[' ) { # array of data - return $data if $data eq '[]'; # return if empty array - - my $_sub_class = substr($class, 6, -1); - my @_json_data = json_decode $data; - my @_values = (); - foreach my $_value (@_json_data) { - push @_values, $self->deserialize($_sub_class, $_value); - } - $_result = \@_values; - } elsif ($class eq 'DateTime') { - $_result = DateTime->from_epoch(epoch => str2time($data)); - } elsif (grep /^$data$/, ('string', 'int', 'float', 'bool')) { #TODO revise the primitive type - $_result= $data; - } else { # model - my $_instance = use_module("WWW::{{invokerPackage}}::Object::$class")->new; - $_result = $_instance->from_hash(decode_json $data); - } - - return $_result; - -} - -# return 'Accept' based on an array of accept provided -# @param [Array] header_accept_array Array fo 'Accept' -# @return String Accept (e.g. application/json) -sub select_header_accept -{ - my ($self, @header) = @_; - - if (@header == 0 || (@header == 1 && $header[0] eq '')) { - return undef; - } elsif (grep(/^application\/json$/i, @header)) { - return 'application/json'; - } else { - return join(',', @header); - } - -} - -# return the content type based on an array of content-type provided -# @param [Array] content_type_array Array fo content-type -# @return String Content-Type (e.g. application/json) -sub select_header_content_type -{ - my ($self, @header) = @_; - - if (@header == 0 || (@header == 1 && $header[0] eq '')) { - return 'application/json'; # default to application/json - } elsif (grep(/^application\/json$/i, @header)) { - return 'application/json'; - } else { - return join(',', @header); - } - -} - -# update hearder and query param based on authentication setting -# -# @param array $headerParams header parameters (by ref) -# @param array $queryParams query parameters (by ref) -# @param array $authSettings array of authentication scheme (e.g ['api_key']) -sub update_params_for_auth { - my ($self, $header_params, $query_params, $auth_settings) = @_; - - return if (scalar(@$auth_settings) == 0) - - # one endpoint can have more than 1 auth settings - foreach my $auth (@$auth_settings) { - # determine which one to use - if (!defined($auth)) { - } - {{#authMethods}} - elsif ($auth eq '{{name}}') { - {{#isApiKey}}{{#isKeyInHeader}}$header_params->{'{{keyParamName}}'} = $self->get_api_key_with_prefix('{{keyParamName}}');{{/isKeyInHeader}}{{#isKeyInQuery}}$query_params->{'{{keyParamName}}'} = $self->get_api_key_with_prefix('{{keyParamName}}');{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}$header_params->{'Authorization'} = 'Basic '.encode_base64(Configuration::username.":".Configuration::password);{{/isBasic}} - {{#isOAuth}}//TODO support oauth{{/isOAuth}} - }{{/authMethods}} - else { - //TODO show warning about security definition not found - } - } -} - - -1; From 0423e0a2dfb211eafc56cba0a970d85e86f63e62 Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 4 Jun 2015 21:12:26 +0800 Subject: [PATCH 69/72] support object response --- .../swagger/codegen/languages/PerlClientCodegen.java | 6 ++++-- .../src/main/resources/perl/APIClient.mustache | 2 +- .../client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java index 74670f27e09..b96b012abba 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PerlClientCodegen.java @@ -27,8 +27,8 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig { public PerlClientCodegen() { super(); - modelPackage = "/Object"; - outputFolder = "generated-code/perl"; + modelPackage = File.separatorChar + "Object"; + outputFolder = "generated-code" + File.separatorChar + "perl"; modelTemplateFiles.put("object.mustache", ".pm"); apiTemplateFiles.put("api.mustache", ".pm"); templateDir = "perl"; @@ -63,6 +63,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig { languageSpecificPrimitives.add("DateTime"); languageSpecificPrimitives.add("ARRAY"); languageSpecificPrimitives.add("HASH"); + languageSpecificPrimitives.add("object"); typeMapping.put("integer", "int"); typeMapping.put("long", "int"); @@ -75,6 +76,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("password", "string"); typeMapping.put("array", "ARRAY"); typeMapping.put("map", "HASH"); + typeMapping.put("object", "object"); supportingFiles.add(new SupportingFile("ApiClient.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "ApiClient.pm")); supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "Configuration.pm")); diff --git a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache index 1d71ca3f99a..2bcdd6da690 100644 --- a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache @@ -216,7 +216,7 @@ sub deserialize $_result = \@_values; } elsif ($class eq 'DateTime') { $_result = DateTime->from_epoch(epoch => str2time($data)); - } elsif (grep /^$data$/, ('string', 'int', 'float', 'bool')) { #TODO revise the primitive type + } elsif (grep /^$class$/, ('string', 'int', 'float', 'bool', 'object')) { #TODO revise the primitive type $_result= $data; } else { # model my $_instance = use_module("WWW::{{invokerPackage}}::Object::$class")->new; diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm index 0ac34355c4c..da29b3e246a 100644 --- a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm +++ b/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm @@ -216,7 +216,7 @@ sub deserialize $_result = \@_values; } elsif ($class eq 'DateTime') { $_result = DateTime->from_epoch(epoch => str2time($data)); - } elsif (grep /^$data$/, ('string', 'int', 'float', 'bool')) { #TODO revise the primitive type + } elsif (grep /^$class$/, ('string', 'int', 'float', 'bool', 'object')) { #TODO revise the primitive type $_result= $data; } else { # model my $_instance = use_module("WWW::SwaggerClient::Object::$class")->new; From ba227b7e727f18c5c3d2ff6fe906b072a5237a04 Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 4 Jun 2015 21:19:16 +0800 Subject: [PATCH 70/72] rename api client --- .../resources/{perl/APIClient.mustache => perlApiClient.mustache} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/swagger-codegen/src/main/resources/{perl/APIClient.mustache => perlApiClient.mustache} (100%) diff --git a/modules/swagger-codegen/src/main/resources/perl/APIClient.mustache b/modules/swagger-codegen/src/main/resources/perlApiClient.mustache similarity index 100% rename from modules/swagger-codegen/src/main/resources/perl/APIClient.mustache rename to modules/swagger-codegen/src/main/resources/perlApiClient.mustache From a1f156ca1948c5d873a91411d157fee2aca90c8d Mon Sep 17 00:00:00 2001 From: Fredrik Gustafsson Date: Fri, 29 May 2015 10:53:48 +0200 Subject: [PATCH 71/72] Updated 'api.mustache' to generate asynchronous methods aswell --- .../src/main/resources/csharp/api.mustache | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/resources/csharp/api.mustache b/modules/swagger-codegen/src/main/resources/csharp/api.mustache index 8e4a468add3..b5c8bfaeac2 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/api.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/api.mustache @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using RestSharp; using {{invokerPackage}}; using {{modelPackage}}; @@ -103,7 +104,49 @@ namespace {{package}} { {{#returnType}}return ({{{returnType}}}) apiClient.Deserialize(response.Content, typeof({{{returnType}}}));{{/returnType}}{{^returnType}} return;{{/returnType}} } + + /// + /// {{summary}} {{notes}} + /// +{{#allParams}} /// {{description}} +{{/allParams}} + /// {{#returnType}}{{{returnType}}}{{/returnType}} + public async {{#returnType}}Task<{{{returnType}}}>{{/returnType}}{{^returnType}}Task{{/returnType}} {{nickname}}Async ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { + + var _request = new RestRequest("{{path}}", Method.{{httpMethod}}); + + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}"); + {{/required}}{{/allParams}} + + // add default header, if any + foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) + { + _request.AddHeader(defaultHeader.Key, defaultHeader.Value); + } + + _request.AddUrlSegment("format", "json"); // set format to json by default + {{#pathParams}}_request.AddUrlSegment("{{baseName}}", ApiInvoker.ParameterToString({{{paramName}}})); // path (url segment) parameter + {{/pathParams}} + {{#queryParams}} if ({{paramName}} != null) _request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // query parameter + {{/queryParams}} + {{#headerParams}} if ({{paramName}} != null) _request.AddHeader("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // header parameter + {{/headerParams}} + {{#formParams}}if ({{paramName}} != null) {{#isFile}}_request.AddFile("{{baseName}}", {{paramName}});{{/isFile}}{{^isFile}}_request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // form parameter{{/isFile}} + {{/formParams}} + {{#bodyParam}}_request.AddParameter("application/json", ApiInvoker.Serialize({{paramName}}), ParameterType.RequestBody); // http body (model) parameter + {{/bodyParam}} + + // make the HTTP request + IRestResponse response = await restClient.ExecuteTaskAsync(_request); + if (((int)response.StatusCode) >= 400) { + throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content); + } + {{#returnType}}return ({{{returnType}}}) ApiInvoker.Deserialize(response.Content, typeof({{{returnType}}}));{{/returnType}}{{^returnType}} + return;{{/returnType}} + } {{/operation}} - } + } {{/operations}} } From 31c6a0a9da90652c8e7f91006eed295f161bc5a3 Mon Sep 17 00:00:00 2001 From: Fredrik Gustafsson Date: Fri, 29 May 2015 12:19:28 +0200 Subject: [PATCH 72/72] Extended the api-class generation by a interface generation --- .../main/resources/csharp/ApiClient.mustache | 14 +++- .../src/main/resources/csharp/api.mustache | 65 ++++++++++++------- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache index c5b72977cf5..ad57cffdf34 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Net; using System.Text; +using System.Threading.Tasks; using Newtonsoft.Json; using RestSharp; @@ -36,7 +37,16 @@ namespace {{invokerPackage}} { private Dictionary defaultHeaderMap = new Dictionary(); - public Object CallApi(String Path, RestSharp.Method Method, Dictionary QueryParams, String PostBody, + public Object CallApi(String Path, RestSharp.Method Method, Dictionary QueryParams, String PostBody, + Dictionary HeaderParams, Dictionary FormParams, Dictionary FileParams, String[] AuthSettings) { + var response = Task.Run(async () => { + var resp = await CallApiAsync(Path, Method, QueryParams, PostBody, HeaderParams, FormParams, FileParams, AuthSettings); + return resp; + }); + return response.Result; + } + + public async Task CallApiAsync(String Path, RestSharp.Method Method, Dictionary QueryParams, String PostBody, Dictionary HeaderParams, Dictionary FormParams, Dictionary FileParams, String[] AuthSettings) { var request = new RestRequest(Path, Method); @@ -67,7 +77,7 @@ namespace {{invokerPackage}} { request.AddParameter("application/json", PostBody, ParameterType.RequestBody); // http body (model) parameter } - return (Object)restClient.Execute(request); + return (Object) await restClient.ExecuteTaskAsync(request); } diff --git a/modules/swagger-codegen/src/main/resources/csharp/api.mustache b/modules/swagger-codegen/src/main/resources/csharp/api.mustache index b5c8bfaeac2..6cb3178e65e 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/api.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/api.mustache @@ -9,10 +9,30 @@ using {{modelPackage}}; namespace {{package}} { {{#operations}} + + public interface I{{classname}} { + {{#operation}} + /// + /// {{summary}} {{notes}} + /// + {{#allParams}}/// {{description}}{{/allParams}} + /// {{#returnType}}{{{returnType}}}{{/returnType}} + {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + /// + /// {{summary}} {{notes}} + /// + {{#allParams}}/// {{description}}{{/allParams}} + /// {{#returnType}}{{{returnType}}}{{/returnType}} + {{#returnType}}Task<{{{returnType}}}>{{/returnType}}{{^returnType}}Task{{/returnType}} {{nickname}}Async ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/operation}} + } + /// /// Represents a collection of functions to interact with the API endpoints /// - public class {{classname}} { + public class {{classname}} : I{{classname}} { + /// /// Initializes a new instance of the class. /// @@ -62,8 +82,7 @@ namespace {{package}} { /// /// {{summary}} {{notes}} /// -{{#allParams}} /// {{description}} -{{/allParams}} + {{#allParams}}/// {{description}}{{/allParams}} /// {{#returnType}}{{{returnType}}}{{/returnType}} public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { @@ -108,38 +127,40 @@ namespace {{package}} { /// /// {{summary}} {{notes}} /// -{{#allParams}} /// {{description}} -{{/allParams}} + {{#allParams}}/// {{description}}{{/allParams}} /// {{#returnType}}{{{returnType}}}{{/returnType}} public async {{#returnType}}Task<{{{returnType}}}>{{/returnType}}{{^returnType}}Task{{/returnType}} {{nickname}}Async ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { - var _request = new RestRequest("{{path}}", Method.{{httpMethod}}); - {{#allParams}}{{#required}} - // verify the required parameter '{{paramName}}' is set - if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}"); + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}"); {{/required}}{{/allParams}} - // add default header, if any - foreach(KeyValuePair defaultHeader in ApiInvoker.GetDefaultHeader()) - { - _request.AddHeader(defaultHeader.Key, defaultHeader.Value); - } - - _request.AddUrlSegment("format", "json"); // set format to json by default - {{#pathParams}}_request.AddUrlSegment("{{baseName}}", ApiInvoker.ParameterToString({{{paramName}}})); // path (url segment) parameter + var path = "{{path}}"; + path = path.Replace("{format}", "json"); + {{#pathParams}}path = path.Replace("{" + "{{baseName}}" + "}", apiClient.ParameterToString({{{paramName}}})); {{/pathParams}} - {{#queryParams}} if ({{paramName}} != null) _request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // query parameter + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + + {{#queryParams}} if ({{paramName}} != null) queryParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // query parameter {{/queryParams}} - {{#headerParams}} if ({{paramName}} != null) _request.AddHeader("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // header parameter + {{#headerParams}} if ({{paramName}} != null) headerParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // header parameter {{/headerParams}} - {{#formParams}}if ({{paramName}} != null) {{#isFile}}_request.AddFile("{{baseName}}", {{paramName}});{{/isFile}}{{^isFile}}_request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // form parameter{{/isFile}} + {{#formParams}}if ({{paramName}} != null) {{#isFile}}fileParams.Add("{{baseName}}", {{paramName}});{{/isFile}}{{^isFile}}formParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // form parameter{{/isFile}} {{/formParams}} - {{#bodyParam}}_request.AddParameter("application/json", ApiInvoker.Serialize({{paramName}}), ParameterType.RequestBody); // http body (model) parameter + {{#bodyParam}}postBody = apiClient.Serialize({{paramName}}); // http body (model) parameter {{/bodyParam}} + // authentication setting, if any + String[] authSettings = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + // make the HTTP request - IRestResponse response = await restClient.ExecuteTaskAsync(_request); + IRestResponse response = (IRestResponse) await apiClient.CallApiAsync(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content); }