fpopenapi.generators.pp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608
  1. {
  2. This file is part of the Free Component Library
  3. Copyright (c) 2024 by Michael Van Canneyt [email protected]
  4. Open API code generators
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit fpopenapi.generators;
  12. {$mode ObjFPC}{$H+}
  13. interface
  14. uses
  15. {$IFDEF FPC_DOTTEDUNITS}
  16. System.Classes, System.SysUtils, System.DateUtils, System.Contnrs, Pascal.CodeGenerator,
  17. {$ELSE}
  18. Classes, SysUtils, strutils, dateutils, pascodegen, inifiles,
  19. {$ENDIF}
  20. fpjson.schema.types,
  21. fpjson.schema.Pascaltypes,
  22. fpjson.schema.codegen,
  23. fpopenapi.objects,
  24. fpopenapi.types,
  25. fpopenapi.pascaltypes;
  26. Const
  27. DefaultServerProxyName = 'TServerProxy';
  28. DefaultServerProxyParent = 'TDataModule';
  29. DefaultServerProxyParentUnit = 'Classes';
  30. type
  31. { TJSONSchemaCodeGeneratorHelper }
  32. // Helper class to generate an API unit header
  33. // And to get access
  34. TJSONSchemaCodeGeneratorHelper = class helper for TJSONSchemaCodeGenerator
  35. procedure GenerateAPIheader;
  36. function ApiData: TAPIData;
  37. end;
  38. { TOpenApiPascalCodeGen }
  39. TOpenApiPascalCodeGen = class(TJSONSchemaCodeGenerator)
  40. private
  41. function GetData: TAPIData;
  42. protected
  43. procedure GenerateHeader; override;
  44. public
  45. property APIData: TAPIData read GetData;
  46. end;
  47. { TDtoCodeGen }
  48. TDtoCodeGen = class(TTypeCodeGenerator)
  49. protected
  50. procedure GenerateHeader; override;
  51. end;
  52. { TSerializerCodeGen }
  53. TSerializerCodeGen = class(TSerializerCodeGenerator)
  54. protected
  55. function MustSerializeType(aType : TPascalTypeData) : boolean; override;
  56. procedure GenerateHeader; override;
  57. end;
  58. { TIntfCodeGen }
  59. { TOpenAPIServiceCodeGen }
  60. TOpenAPIServiceCodeGen = class(TOpenApiPascalCodeGen)
  61. private
  62. FDefineServiceResultType: boolean;
  63. FDtoUnit: string;
  64. FSerializerUnit: string;
  65. FServiceName: string;
  66. FAsync: boolean;
  67. FServiceRequestIDType: string;
  68. FServiceResultType: string;
  69. function GetServiceRequestIDType: string;
  70. function GetServiceResultType: string;
  71. protected
  72. procedure WriteResultTypes; virtual;
  73. procedure WriteCallbackTypes; virtual;
  74. procedure GenerateAuxiliaryTypes; virtual;
  75. procedure GenerateServiceResultType; virtual;
  76. function GenerateClientServiceMethodDecl(aMethod: TAPIServiceMethod; const aClassName: string): string; virtual;
  77. procedure GetMethodCallbackTypeNames(aTypes: TStrings); virtual;
  78. procedure GetMethodResultTypeNames(aTypes: TStrings); virtual;
  79. function GetMethodResultType(aMethod: TAPIServiceMethod): string; virtual;
  80. function MethodResultCallBackName(aMethod: TAPIServiceMethod): string; virtual;
  81. function ParameterToArg(Idx: integer; aParam: TAPIServiceMethodParam): string; virtual;
  82. public
  83. constructor Create(AOwner: TComponent); override;
  84. property ServiceName: string read FServiceName write FServiceName;
  85. property DtoUnit: string read FDtoUnit write FDtoUnit;
  86. property SerializerUnit: string read FSerializerUnit write FSerializerUnit;
  87. property AsyncService: boolean read FAsync write FAsync;
  88. property ServiceResultType: string read GetServiceResultType write FServiceResultType;
  89. property DefineServiceResultType: boolean read FDefineServiceResultType write FDefineServiceResultType;
  90. property ServiceRequestIDType: string read GetServiceRequestIDType write FServiceRequestIDType;
  91. end;
  92. { TServiceInterfaceCodeGen }
  93. TServiceInterfaceCodeGen = class(TOpenAPIServiceCodeGen)
  94. protected
  95. procedure GenerateServiceInterface(aService: TAPIService); virtual;
  96. public
  97. procedure Execute(aData: TAPIData); virtual;
  98. end;
  99. { TServiceImplementationCodeGen }
  100. TServiceImplementationCodeGen = class(TOpenAPIServiceCodeGen)
  101. private
  102. FParentHasCancelRequest: boolean;
  103. FServiceInterfaceUnit: string;
  104. FServiceParentClass: string;
  105. FServiceParentUnit: string;
  106. procedure SetServiceInterfaceUnit(AValue: string);
  107. protected
  108. procedure GenerateCancelRequest(aService: TAPIService); virtual;
  109. procedure GenerateConstructor(aService: TAPIService); virtual;
  110. procedure GenerateServiceImplementationImpl(aService: TAPIService); virtual;
  111. procedure GenerateServiceMethodImpl(aService: TAPIService; aMethod: TAPIServiceMethod); virtual;
  112. procedure GenerateURLConstruction(aService: TAPIService; aMethod: TAPIServiceMethod); virtual;
  113. procedure GenerateServiceImplementationDecl(aService: TAPIService); virtual;
  114. public
  115. constructor Create(AOwner: TComponent); override;
  116. procedure Execute(aData: TAPIData); virtual;
  117. property ServiceInterfaceUnit: string read FServiceInterfaceUnit write SetServiceInterfaceUnit;
  118. property ServiceParentClass: string read FServiceParentClass write FServiceParentClass;
  119. property ServiceParentUnit: string read FServiceParentUnit write FServiceParentUnit;
  120. property ParentHasCancelRequest: boolean read FParentHasCancelRequest write FParentHasCancelRequest;
  121. end;
  122. { TServerModuleCodeGen }
  123. { TServerCodeGen }
  124. TServerCodeGen = class(TOpenAPIServiceCodeGen)
  125. private
  126. FModuleParentUnit: string;
  127. function GetModuleParentUnit: string;
  128. protected
  129. procedure GenerateServerServiceMethodImpl(lMethod: TAPIserviceMethod; const aClassName: string);
  130. // needed for service registration
  131. function GetMethodHandleRequestName(aMethod: TAPIServiceMethod; const aClassName: string): string; virtual;
  132. function GetServerServiceHandleMethodDecl(aMethod: TAPIServiceMethod; const aClassName: string = ''): string; virtual;
  133. // Methods for the actual implementation
  134. function GetMethodParameterDecl(aMethod: TAPIServiceMethod; aParam: TAPIServiceMethodParam): string; virtual;
  135. function GetMethodArgs(aMethod: TAPIServiceMethod): string; virtual;
  136. function GetServerServiceMethodDecl(aMethod: TAPIServiceMethod; const aClassName: string = ''): string; virtual;
  137. procedure GenerateServerServiceImplementationImpl(aService: TAPIService; const aModuleName: string; isAbstract: boolean); virtual;
  138. procedure GenerateServerServiceImplementationDecl(aService: TAPIService;
  139. aParentModule, aModuleName: string; isAbstract: boolean; isHandler: boolean); virtual;
  140. public
  141. property ModuleParentUnit: string read GetModuleParentUnit write FModuleParentUnit;
  142. end;
  143. // This module generates a complete module that handles the HTTP Requests and hands them off.
  144. { TServerModuleHandlerCodeGen }
  145. TServerModuleHandlerCodeGen = class(TServerCodeGen)
  146. private
  147. FAbstractServiceCalls: boolean;
  148. FModuleParentClass: string;
  149. class function ConvertToRouteParams(const aPath: string): string;
  150. function GetModuleParentCLass: string;
  151. protected
  152. procedure GenerateRegisterAPIRoutes(aClassName: string; aService: TAPIService); virtual;
  153. procedure GenerateServerServiceImplementationImpl(aService: TAPIService; const aModuleName: string; isAbstract: boolean); override;
  154. procedure WriteConvertArgument(aMethod: TAPIServiceMethod; aParam: TAPIServiceMethodParam); virtual;
  155. procedure GenerateServerServiceHandleMethodImpl(lMethod: TAPIserviceMethod; const aClassName: string); virtual;
  156. public
  157. procedure Execute(aData: TAPIData); virtual;
  158. property AbstractServiceCalls: boolean read FAbstractServiceCalls write FAbstractServiceCalls;
  159. property ModuleParentClass: string read GetModuleParentClass write FModuleParentClass;
  160. end;
  161. // This module generates a descendant of the server module.
  162. // Can be used when TServerModuleCodeGen is used with AbstractServiceCalls = True
  163. { TServerImplementationModuleCodeGen }
  164. TServerImplementationModuleCodeGen = class(TServerCodeGen)
  165. public
  166. procedure Execute(aData: TAPIData); virtual;
  167. end;
  168. { TServerServiceModule }
  169. { TServerProxyServiceModule }
  170. { TServerProxyServiceModuleCodeGen }
  171. TServerProxyServiceModuleCodeGen = class(TOpenApiPascalCodeGen)
  172. private
  173. FFormFile: Boolean;
  174. FProxyClassName: string;
  175. FProxyParentClass: string;
  176. FProxyParentUnit: string;
  177. FProxyVarName: String;
  178. FServiceImplementationUnit: string;
  179. FServiceInterfaceUnit: string;
  180. FUseInterfaceType: Boolean;
  181. FForm : TStrings;
  182. procedure CheckDefaults;
  183. function GetProxyVarName: String;
  184. procedure SetProxyClassName(const aValue: string);
  185. Protected
  186. public
  187. constructor Create(AOwner: TComponent); override;
  188. Destructor Destroy; override;
  189. procedure GenerateModule;
  190. procedure GenerateFormFile;
  191. procedure Execute(aData: TAPIData); virtual;
  192. property ServiceInterfaceUnit: string read FServiceInterfaceUnit write FServiceInterfaceUnit;
  193. property ServiceImplementationUnit: string read FServiceImplementationUnit write FServiceImplementationUnit;
  194. property ProxyParentClass: string read FProxyParentClass write FProxyParentClass;
  195. property ProxyParentUnit: string read FProxyParentUnit write FProxyParentUnit;
  196. Property UseInterfaceType : Boolean Read FUseInterfaceType Write FUseInterfaceType;
  197. Property ProxyClassName : string Read FProxyClassName Write SetProxyClassName;
  198. Property ProxyVarName : String Read GetProxyVarName Write FProxyVarName;
  199. Property FormFile : Boolean Read FFormFile Write FFormFile;
  200. Property Form : TStrings Read FForm Write FForm;
  201. end;
  202. implementation
  203. { TJSONSchemaCodeGeneratorHelper }
  204. procedure TJSONSchemaCodeGeneratorHelper.GenerateAPIheader;
  205. var
  206. S, lTitle, lDate, lVersion: string;
  207. lDescription: TStrings;
  208. I: integer;
  209. begin
  210. lDescription:=nil;
  211. lDate:=FormatDateTime('yyyy"-"mm"-"dd hh":"nn', Now);
  212. lVersion:=APIData.API.Info.Version;
  213. lTitle:=APIData.API.Info.Title;
  214. if VerboseHeader and (APIData.API.Info.Description<>'') then
  215. begin
  216. lDescription:=TStringList.Create;
  217. lDescription.Text:=APIData.API.Info.Description;
  218. end;
  219. Addln('{ -----------------------------------------------------------------------');
  220. Indent;
  221. Addln('Do not edit !');
  222. Addln('');
  223. Addln('This file was automatically generated on %s.', [lDate]);
  224. S:='';
  225. for I:=1 to ParamCount do
  226. S:=S+' '+ParamStr(i);
  227. Addln('Used command-line parameters:');
  228. Indent;
  229. Addln(S);
  230. Undent;
  231. Addln('Source OpenAPI document data:');
  232. Indent;
  233. if lTitle<>'' then
  234. Addln('Title: %s', [lTitle]);
  235. if lVersion<>'' then
  236. Addln('Version: %s', [lVersion]);
  237. if Assigned(lDescription) then
  238. begin
  239. Addln('Description:');
  240. for S in lDescription do
  241. AddLn(S);
  242. end;
  243. Undent;
  244. Undent;
  245. Addln(' -----------------------------------------------------------------------}');
  246. FreeAndNil(lDescription);
  247. end;
  248. function TJSONSchemaCodeGeneratorHelper.ApiData: TAPIData;
  249. begin
  250. Result:=TypeData as TAPIData;
  251. end;
  252. { TOpenAPICodeGen }
  253. function TOpenApiPascalCodeGen.GetData: TAPIData;
  254. begin
  255. Result:=TypeData as TAPIData;
  256. end;
  257. procedure TOpenApiPascalCodeGen.GenerateHeader;
  258. begin
  259. GenerateAPIheader;
  260. end;
  261. { TDtoCodeGen }
  262. procedure TDtoCodeGen.GenerateHeader;
  263. begin
  264. GenerateAPIheader;
  265. end;
  266. { TSerializerCodeGen }
  267. function TSerializerCodeGen.MustSerializeType(aType: TPascalTypeData): boolean;
  268. begin
  269. Result:=inherited MustSerializeType(aType);
  270. if Result and (aType is TAPITypeData) then
  271. Result:=Not TAPITypeData(aType).BinaryData;
  272. end;
  273. procedure TSerializerCodeGen.GenerateHeader;
  274. begin
  275. GenerateAPIheader;
  276. end;
  277. { TOpenAPIerviceCodeGen }
  278. function TOpenAPIServiceCodeGen.MethodResultCallBackName(aMethod:
  279. TAPIServiceMethod): string;
  280. begin
  281. Result:=GetMethodResultType(aMethod);
  282. if Result<>'' then
  283. Result:=Result+'Callback';
  284. end;
  285. function TOpenAPIServiceCodeGen.ParameterToArg(Idx: integer;
  286. aParam: TAPIServiceMethodParam): string;
  287. begin
  288. Result:=Format('%s : %s', [aParam.Name, aParam.TypeName]);
  289. if aParam.DefaultValue<>'' then
  290. Result:=Result+' = '+aParam.DefaultValue;
  291. end;
  292. constructor TOpenAPIServiceCodeGen.Create(AOwner: TComponent);
  293. begin
  294. inherited Create(AOwner);
  295. DefineServiceResultType:=False;
  296. end;
  297. function TOpenAPIServiceCodeGen.GetServiceResultType: string;
  298. begin
  299. Result:=FServiceResultType;
  300. if Result = '' then
  301. Result:='TServiceResult';
  302. end;
  303. function TOpenAPIServiceCodeGen.GetServiceRequestIDType: string;
  304. begin
  305. Result:=FServiceRequestIDType;
  306. if Result = '' then
  307. Result:='TRESTServiceRequestID';
  308. end;
  309. procedure TOpenAPIServiceCodeGen.GenerateServiceResultType;
  310. begin
  311. if AsyncService then
  312. begin
  313. Addln('%s = string;', [ServiceRequestIDType]);
  314. Addln('');
  315. end;
  316. if not DelphiCode then
  317. Addln('generic %s<T> = record', [ServiceResultType])
  318. else
  319. Addln(' %s<T> = record', [ServiceResultType]);
  320. Indent;
  321. Addln('StatusCode : Integer;');
  322. Addln('StatusText : String;');
  323. if AsyncService then
  324. Addln('RequestID : %s;', [ServiceRequestIDType]);
  325. Addln('Value : T;');
  326. Undent;
  327. AddLn('end;');
  328. AddLn('');
  329. end;
  330. function TOpenAPIServiceCodeGen.GenerateClientServiceMethodDecl(aMethod: TAPIServiceMethod; const aClassName: string): string;
  331. procedure AddTo(var S: string; const T: string);
  332. begin
  333. if T = '' then exit;
  334. if S<>'' then
  335. S:=S+'; ';
  336. S:=S+T;
  337. end;
  338. var
  339. lBodyType, lResultType, lName, lParams: string;
  340. I: integer;
  341. begin
  342. lParams:='';
  343. // Non-optional
  344. for I:=0 to aMethod.ParamCount-1 do
  345. if aMethod.Param[I].DefaultValue = '' then
  346. AddTo(lParams, ParameterToArg(I, aMethod.Param[I]));
  347. if Assigned(aMethod.RequestBodyDataType) then
  348. lBodyType:=aMethod.RequestBodyDataType.GetTypeName(ntPascal);
  349. if lBodyType<>'' then
  350. AddTo(lParams, 'aRequest : '+lBodyType);
  351. if aMethod.ResultDataType.BinaryData then
  352. AddTo(lParams, 'aResponseStream : TStream');
  353. if AsyncService then
  354. AddTo(lParams, 'aCallback : '+MethodResultCallbackName(aMethod));
  355. // Optional
  356. for I:=0 to aMethod.ParamCount-1 do
  357. if aMethod.Param[I].DefaultValue<>'' then
  358. AddTo(lParams, ParameterToArg(I, aMethod.Param[I]));
  359. lName:=aMethod.MethodName;
  360. if aClassName<>'' then
  361. lName:=aClassName+'.'+lName;
  362. if AsyncService then
  363. Result:=Format('Function %s(%s) : %s;', [lName, lParams, ServiceRequestIDType])
  364. else
  365. begin
  366. lResultType:=GetMethodResultType(aMethod);
  367. Result:=Format('Function %s(%s) : %s;', [lName, lParams, lResultType]);
  368. end;
  369. end;
  370. procedure TOpenAPIServiceCodeGen.GetMethodCallbackTypeNames(aTypes: TStrings);
  371. var
  372. I, J: integer;
  373. lName: string;
  374. lService: TAPIService;
  375. lMethod: TAPIServiceMethod;
  376. begin
  377. for I:=0 to APIData.ServiceCount-1 do
  378. begin
  379. lService:=APIData.Services[I];
  380. if (Self.ServiceName = '') or SameText(lService.ServiceName, Self.ServiceName) then
  381. for J:=0 to lService.MethodCount-1 do
  382. begin
  383. lMethod:=lService.Methods[J];
  384. if lMethod.ResultDataType<>nil then
  385. begin
  386. lName:=MethodResultCallBackName(lMethod);
  387. if lName<>'TVoidResultCallBack' then
  388. aTypes.AddObject(lName, lMethod);
  389. end;
  390. end;
  391. end;
  392. end;
  393. procedure TOpenAPIServiceCodeGen.GetMethodResultTypeNames(aTypes: TStrings);
  394. var
  395. I, J: integer;
  396. lName: string;
  397. lService: TAPIService;
  398. lMethod: TAPIServiceMethod;
  399. begin
  400. for I:=0 to APIData.ServiceCount-1 do
  401. begin
  402. lService:=APIData.Services[I];
  403. if (Self.ServiceName = '') or SameText(lService.ServiceName, Self.ServiceName) then
  404. for J:=0 to lService.MethodCount-1 do
  405. begin
  406. lMethod:=lService.Methods[J];
  407. if lMethod.ResultDataType<>nil then
  408. begin
  409. lName:=GetMethodResultType(lMethod);
  410. if lName<>'' then
  411. aTypes.AddObject(lName, lMethod);
  412. end;
  413. end;
  414. end;
  415. end;
  416. function TOpenAPIServiceCodeGen.GetMethodResultType(aMethod: TAPIServiceMethod): string;
  417. begin
  418. Result:=aMethod.ResultDtoType;
  419. if Result<>'' then
  420. Result:=Result+'ServiceResult'
  421. else
  422. Result:='TVoidServiceResult';
  423. end;
  424. { TServiceInterfaceCodeGen }
  425. procedure TServiceInterfaceCodeGen.GenerateServiceInterface(aService: TAPIService);
  426. var
  427. I: integer;
  428. lDecl, lParent: string;
  429. lMethod: TAPIServiceMethod;
  430. begin
  431. DoLog('Generating service interface %s (UUID: %s)',
  432. [aService.ServiceName, aService.ServiceUUID]);
  433. lParent:=aService.ServiceParentInterface;
  434. if lParent<>'' then
  435. lParent:='('+lParent+')';
  436. Addln('// Service %s', [aService.ServiceInterfaceName]);
  437. Addln('');
  438. Addln('%s = interface %s [''%s'']', [aService.ServiceInterfaceName,
  439. lParent, aService.ServiceUUID]);
  440. indent;
  441. for I:=0 to aService.MethodCount-1 do
  442. begin
  443. lMethod:=aService.Methods[I];
  444. lDecl:=GenerateClientServiceMethodDecl(lMethod, '');
  445. Addln(lDecl);
  446. end;
  447. if AsyncService then
  448. Addln('Procedure CancelRequest(aRequestID : %s);', [ServiceRequestIDType]);
  449. undent;
  450. Addln('end;');
  451. Addln('');
  452. end;
  453. procedure TOpenAPIServiceCodeGen.WriteResultTypes;
  454. var
  455. I: integer;
  456. lName, lDef, lResType: string;
  457. lTypes: TStringList;
  458. begin
  459. Addln('// Service result types');
  460. lTypes:=TStringList.Create;
  461. try
  462. lTypes.Sorted:=True;
  463. lTypes.Duplicates:=dupIgnore;
  464. GetMethodResultTypeNames(lTypes);
  465. lTypes.Sorted:=False;
  466. for I:=0 to lTypes.Count-1 do
  467. begin
  468. lName:=lTypes[I];
  469. lResType:=TAPIServiceMethod(lTypes.objects[I]).ResultDtoType;
  470. lDef:=Format('%s<%s>', [ServiceResultType, lResType]);
  471. if not DelphiCode then
  472. lDef:='specialize '+lDef;
  473. Addln('%s = %s;', [lName, lDef]);
  474. end;
  475. Addln('');
  476. finally
  477. lTypes.Free;
  478. end;
  479. end;
  480. procedure TOpenAPIServiceCodeGen.WriteCallbackTypes;
  481. var
  482. I: integer;
  483. lName, lDef: string;
  484. lTypes: TStringList;
  485. begin
  486. Addln('// Service Callback types');
  487. lTypes:=TStringList.Create;
  488. try
  489. lTypes.Sorted:=True;
  490. lTypes.Duplicates:=dupIgnore;
  491. GetMethodCallbackTypeNames(lTypes);
  492. lTypes.Sorted:=False;
  493. for I:=0 to lTypes.Count-1 do
  494. begin
  495. lName:=lTypes[I];
  496. lDef:=Format('reference to procedure(aResult : %s)', [lName]);
  497. Addln('%s = %s;', [lName, lDef]);
  498. end;
  499. Addln('');
  500. finally
  501. lTypes.Free;
  502. end;
  503. end;
  504. procedure TOpenAPIServiceCodeGen.GenerateAuxiliaryTypes;
  505. begin
  506. if DefineServiceResultType then
  507. GenerateServiceResultType;
  508. WriteResultTypes;
  509. if AsyncService then
  510. WriteCallbackTypes;
  511. end;
  512. procedure TServiceInterfaceCodeGen.Execute(aData: TAPIData);
  513. var
  514. I: integer;
  515. lService: TAPIService;
  516. begin
  517. SetTypeData(aData);
  518. try
  519. GenerateHeader;
  520. Addln('unit %s;', [Self.OutputUnitName]);
  521. Addln('');
  522. if AsyncService then
  523. GenerateFPCDirectives(['functionreferences'])
  524. else
  525. GenerateFPCDirectives();
  526. Addln('interface');
  527. Addln('');
  528. Addln('uses');
  529. indent;
  530. Addln(' classes, fpopenapiclient, %s;', [DtoUnit]);
  531. undent;
  532. Addln('');
  533. EnsureSection(csType);
  534. indent;
  535. GenerateAuxiliaryTypes;
  536. for I:=0 to aData.ServiceCount-1 do
  537. begin
  538. lService:=aData.Services[I];
  539. if (Self.ServiceName = '') or SameText(lService.ServiceName, Self.ServiceName) then
  540. GenerateServiceInterface(lService);
  541. end;
  542. undent;
  543. Addln('');
  544. Addln('implementation');
  545. Addln('');
  546. Addln('end.');
  547. finally
  548. SetTypeData(nil);
  549. end;
  550. end;
  551. { TServiceImplementationCodeGen }
  552. procedure TServiceImplementationCodeGen.GenerateServiceImplementationDecl(aService: TAPIService);
  553. var
  554. I: integer;
  555. lDecl, lParent: string;
  556. lMethod: TAPIServiceMethod;
  557. lName: string;
  558. begin
  559. lName:=aService.ServiceProxyImplementationClassName;
  560. DoLog('Generating class %s to implement service interface %s', [lName,
  561. aService.ServiceName]);
  562. lParent:=ServiceParentClass;
  563. Addln('// Service %s', [aService.ServiceInterfaceName]);
  564. Addln('');
  565. if ServiceInterfaceUnit<>'' then
  566. Addln('%s = Class (%s,%s)', [lName, lParent, aService.ServiceInterfaceName])
  567. else
  568. Addln('%s = Class (%s)', [lName, lParent]);
  569. Indent;
  570. for I:=0 to aService.MethodCount-1 do
  571. begin
  572. lMethod:=aService.Methods[I];
  573. lDecl:=GenerateClientServiceMethodDecl(lMethod, '');
  574. Addln(lDecl);
  575. end;
  576. if not ParentHasCancelRequest then
  577. Addln('Procedure CancelRequest(aRequestID : TServiceRequestID);');
  578. undent;
  579. Addln('end;');
  580. Addln('');
  581. end;
  582. constructor TServiceImplementationCodeGen.Create(AOwner: TComponent);
  583. begin
  584. inherited Create(AOwner);
  585. ServiceParentClass:='TFPOpenAPIServiceClient';
  586. ServiceParentUnit:='fpopenapiclient';
  587. end;
  588. procedure TServiceImplementationCodeGen.GenerateConstructor(aService: TAPIService);
  589. var
  590. lName: string;
  591. begin
  592. lName:=aService.ServiceProxyImplementationClassName;
  593. Addln('Constructor %s.Create(aOwner : TComponent; aWebClient : TFPAbstractWebClient);',
  594. [lName]);
  595. Addln('begin');
  596. indent;
  597. Addln('Inherited Create(aOwner);');
  598. // We can try to put http/authenticator in a parent class ?
  599. Addln('WebClient:=aWebClient;');
  600. undent;
  601. Addln('end;');
  602. Addln('');
  603. end;
  604. procedure TServiceImplementationCodeGen.SetServiceInterfaceUnit(AValue: string);
  605. begin
  606. if FServiceInterfaceUnit = AValue then Exit;
  607. FServiceInterfaceUnit:=AValue;
  608. end;
  609. procedure TServiceImplementationCodeGen.GenerateCancelRequest(aService: TAPIService);
  610. var
  611. lName: string;
  612. begin
  613. lName:=aService.ServiceProxyImplementationClassName;
  614. Addln('Procedure %s.CancelRequest(aRequestID : TServiceRequestID);', [lName]);
  615. Addln('');
  616. Addln('begin');
  617. indent;
  618. Addln('WebClient.CancelRequest(aRequestID);');
  619. undent;
  620. Addln('end;');
  621. Addln('');
  622. end;
  623. procedure TServiceImplementationCodeGen.GenerateURLConstruction(aService: TAPIService; aMethod: TAPIServiceMethod);
  624. var
  625. I: integer;
  626. lParam: TAPIServiceMethodParam;
  627. lParamName: string;
  628. begin
  629. Addln('lURL:=BuildEndPointURL(lMethodURL);');
  630. if aMethod.HasQueryParam then
  631. Addln('lQuery:='''';');
  632. if aMethod.Operation.HasKeyWord(okParameters) then
  633. begin
  634. for I:=0 to aMethod.Operation.Parameters.Count-1 do
  635. begin
  636. lParam:=aMethod.Param[I];
  637. if lParam.Location = plPath then
  638. begin
  639. lParamName:=lParam.OriginalName;
  640. Addln('lUrl:=ReplacePathParam(lURL,''%s'',%s);',
  641. [lParamName, lParam.AsStringValue]);
  642. end;
  643. end;
  644. for I:=0 to aMethod.Operation.Parameters.Count-1 do
  645. begin
  646. lParam:=aMethod.Param[I];
  647. if lParam.Location = plQuery then
  648. begin
  649. lParamName:=lParam.OriginalName;
  650. Addln('lQuery:=ConcatRestParam(lQuery,''%s'',%s);', [lParamName, lParam.AsStringValue]);
  651. end;
  652. end;
  653. end;
  654. if aMethod.HasQueryParam then
  655. Addln('lURL:=lURL+lQuery;');
  656. end;
  657. procedure TServiceImplementationCodeGen.GenerateServiceMethodImpl(aService: TAPIService; aMethod: TAPIServiceMethod);
  658. var
  659. lDecl: string;
  660. lHTTPMethod: string;
  661. lBodyArg: string;
  662. S,lName: string;
  663. lResultType : TAPITypeData;
  664. begin
  665. lName:=aService.ServiceProxyImplementationClassName;
  666. lDecl:=GenerateClientServiceMethodDecl(aMethod, lName);
  667. Addln(lDecl);
  668. Addln('');
  669. Addln('const');
  670. indent;
  671. Addln('lMethodURL = ''%s'';', [aMethod.Path.PathComponent]);
  672. undent;
  673. Addln('');
  674. Addln('var');
  675. indent;
  676. Addln('lURL : String;');
  677. Addln('lResponse : TServiceResponse;');
  678. if aMethod.HasQueryParam then
  679. Addln('lQuery : String;');
  680. undent;
  681. Addln('');
  682. Addln('begin');
  683. indent;
  684. Addln('Result:=Default(%s);', [GetMethodResultType(aMethod)]);
  685. GenerateURLConstruction(aService, aMethod);
  686. lHTTPMethod:=aMethod.Operation.PathComponent;
  687. if (aMethod.RequestBodyDataType=nil) then
  688. lBodyArg:=''''''
  689. else if (not aMethod.RequestBodyDataType.BinaryData) then
  690. lBodyArg:='aRequest.Serialize'
  691. else
  692. lBodyArg:='aRequest';
  693. if aMethod.ResultDataType.BinaryData then
  694. Addln('lResponse:=ExecuteRequest(''%s'',lURL,%s,aResponseStream);', [lHTTPMethod, lBodyArg])
  695. else
  696. Addln('lResponse:=ExecuteRequest(''%s'',lURL,%s);', [lHTTPMethod, lBodyArg]);
  697. AddLn('Result:=%s.Create(lResponse);', [GetMethodResultType(aMethod)]);
  698. lResultType:=aMethod.ResultDataType;
  699. if (aMethod.ResultDataType=nil) then
  700. Addln('Result.Value:=Result.Success;')
  701. else if lResultType.BinaryData then
  702. Addln('Result.Value:=aResponseStream;')
  703. else
  704. begin
  705. Addln('if Result.Success then');
  706. indent;
  707. S:=lResultType.PascalName;
  708. Case lResultType.Pascaltype of
  709. ptSchemaStruct,ptAnonStruct,ptArray:
  710. Addln('Result.Value:=%s.Deserialize(lResponse.Content);', [S]);
  711. ptString,
  712. ptJSON:
  713. Addln('Result.Value:=lResponse.Content;');
  714. ptBoolean:
  715. Addln('Result.Value:=StrToBoolDef(lResponse.Content,False);');
  716. ptInteger:
  717. Addln('Result.Value:=StrToIntDef(lResponse.Content,0);');
  718. ptInt64:
  719. Addln('Result.Value:=StrToInt64Def(lResponse.Content,0);');
  720. ptDateTime:
  721. Addln('Result.Value:=ISO8601ToDateDef(lResponse.Content,0);');
  722. ptFloat32,
  723. ptFloat64:
  724. Addln('Result.Value:=StrToFloatDef(lResponse.Content,0.0);');
  725. ptEnum:
  726. begin
  727. Raise EOpenAPi.Create('Enum result not supported');
  728. end;
  729. end;
  730. Undent;
  731. end;
  732. undent;
  733. Addln('end;');
  734. Addln('');
  735. end;
  736. procedure TServiceImplementationCodeGen.GenerateServiceImplementationImpl(aService: TAPIService);
  737. var
  738. I: integer;
  739. lName: string;
  740. begin
  741. lName:=aService.ServiceProxyImplementationClassName;
  742. DoLog('Generating implementation for class %s', [lName]);
  743. if AsyncService then
  744. GenerateCancelRequest(aService);
  745. for I:=0 to aService.MethodCount-1 do
  746. GenerateServiceMethodImpl(aService, aService.Methods[I]);
  747. end;
  748. procedure TServiceImplementationCodeGen.Execute(aData: TAPIData);
  749. var
  750. I: integer;
  751. lService: TAPIService;
  752. begin
  753. SetTypeData(aData);
  754. GenerateHeader;
  755. Addln('unit %s;', [Self.OutputUnitName]);
  756. Addln('');
  757. if AsyncService then
  758. GenerateFPCDirectives(['functionreferences, anonymousfunctions'])
  759. else
  760. GenerateFPCDirectives();
  761. Addln('interface');
  762. Addln('');
  763. Addln('uses');
  764. indent;
  765. AddLn('classes, fpopenapiclient');
  766. if ServiceInterfaceUnit<>'' then
  767. Addln(', %s // Service definition ', [ServiceInterfaceUnit]);
  768. if (ServiceParentUnit<>'') and not SameText(ServiceParentUnit, 'fpopenapiclient') then
  769. Addln(', %s // Service parent class ', [ServiceParentUnit]);
  770. Addln(', %s;', [DtoUnit]);
  771. undent;
  772. Addln('');
  773. EnsureSection(csType);
  774. indent;
  775. if ServiceInterfaceUnit = '' then
  776. GenerateAuxiliaryTypes;
  777. for I:=0 to aData.ServiceCount-1 do
  778. begin
  779. lService:=aData.Services[I];
  780. if (Self.ServiceName = '') or SameText(lService.ServiceName, Self.ServiceName) then
  781. GenerateServiceImplementationDecl(lService);
  782. end;
  783. undent;
  784. Addln('');
  785. Addln('implementation');
  786. Addln('');
  787. Addln('uses');
  788. indent;
  789. if DelphiCode then
  790. Addln('System.SysUtils')
  791. else
  792. Addln('SysUtils');
  793. Addln(', %s;', [SerializerUnit]);
  794. undent;
  795. Addln('');
  796. for I:=0 to aData.ServiceCount-1 do
  797. begin
  798. lService:=aData.Services[I];
  799. if (Self.ServiceName = '') or SameText(lService.ServiceName, Self.ServiceName) then
  800. GenerateServiceImplementationImpl(lService);
  801. end;
  802. Addln('');
  803. Addln('end.');
  804. end;
  805. { TServerModuleCodeGen }
  806. function TServerCodeGen.GetMethodHandleRequestName(aMethod: TAPIServiceMethod; const aClassName: string): string;
  807. var
  808. lMethodName: string;
  809. begin
  810. lMethodName:=aMethod.MethodName;
  811. lMethodName:='Handle'+lMethodName+'Request';
  812. if aClassName<>'' then
  813. lMethodName:=aClassName+'.'+lMethodName;
  814. Result:=lMethodName;
  815. end;
  816. function TServerCodeGen.GetServerServiceHandleMethodDecl(aMethod: TAPIServiceMethod; const aClassName: string): string;
  817. var
  818. lMethodName: string;
  819. begin
  820. lMethodName:=GetMethodHandleRequestName(aMethod, aClassName);
  821. Result:=Format('Procedure %s(aRequest : TRequest; aResponse : TResponse);',
  822. [lMethodName]);
  823. if aclassName = '' then
  824. Result:=Result+' virtual;';
  825. end;
  826. function TServerCodeGen.GetMethodParameterDecl(aMethod: TAPIServiceMethod;
  827. aParam: TAPIServiceMethodParam): string;
  828. begin
  829. Result:=aParam.Name+': ';
  830. Result:=Result+aParam.TypeName;
  831. end;
  832. function TServerCodeGen.GetMethodArgs(aMethod: TAPIServiceMethod): string;
  833. var
  834. I: integer;
  835. begin
  836. Result:='';
  837. for I:=0 to aMethod.ParamCount-1 do
  838. begin
  839. if Result<>'' then
  840. Result:=Result+'; ';
  841. Result:=Result+GetMethodParameterDecl(aMethod, aMethod.Param[i]);
  842. end;
  843. if aMethod.RequestBodyDataType<>nil then
  844. begin
  845. if Result<>'' then
  846. Result:=Result+'; ';
  847. Result:=Result+'aRequest : '+aMethod.RequestBodyDataType.PascalName;
  848. end;
  849. end;
  850. function TServerCodeGen.GetServerServiceMethodDecl(aMethod: TAPIServiceMethod; const aClassName: string): string;
  851. var
  852. lMethodArgs: string;
  853. lMethodName: string;
  854. lResultType: string;
  855. begin
  856. lMethodName:=aMethod.MethodName;
  857. if aClassName<>'' then
  858. lMethodName:=aClassName+'.'+lMethodName;
  859. lResultType:=aMethod.ResultDtoType;
  860. lMethodArgs:=GetMethodArgs(aMethod);
  861. if lResultType = '' then
  862. Result:=Format('procedure %s(%s);', [lMethodName, lMethodArgs])
  863. else
  864. Result:=Format('function %s(%s) : %s;', [lMethodName, lMethodArgs, lResultType]);
  865. end;
  866. procedure TServerCodeGen.GenerateServerServiceImplementationDecl(aService: TAPIService;
  867. aParentModule, aModuleName: string; isAbstract: boolean; isHandler: boolean);
  868. var
  869. lDecl: string;
  870. lMethod: TAPIServiceMethod;
  871. I: integer;
  872. begin
  873. Addln('%s = class(%s)', [aModuleName, aParentModule]);
  874. Addln('Public');
  875. Indent;
  876. if IsHandler then
  877. begin
  878. Addln('class Procedure RegisterAPIRoutes(aBaseURL : String; aUseStreaming : Boolean = False); override;');
  879. for I:=0 to aService.MethodCount-1 do
  880. begin
  881. lMethod:=aService.Methods[i];
  882. lDecl:=GetServerServiceHandleMethodDecl(lMethod, '');
  883. Addln(lDecl);
  884. end;
  885. end;
  886. AddLn('');
  887. for I:=0 to aService.MethodCount-1 do
  888. begin
  889. lMethod:=aService.Methods[i];
  890. lDecl:=GetServerServiceMethodDecl(lMethod, '');
  891. if isHandler then
  892. begin
  893. lDecl:=lDecl+' virtual;';
  894. if isAbstract then
  895. lDecl:=lDecl+' abstract;';
  896. end
  897. else
  898. lDecl:=lDecl+' override;';
  899. Addln(lDecl);
  900. end;
  901. undent;
  902. AddLn('end;');
  903. AddLn('');
  904. end;
  905. class function TServerModuleHandlerCodeGen.ConvertToRouteParams(const aPath: string): string;
  906. begin
  907. Result:=StringReplace(aPath, '{', ':', [rfReplaceAll]);
  908. Result:=StringReplace(Result, '}', '', [rfReplaceAll]);
  909. end;
  910. procedure TServerModuleHandlerCodeGen.GenerateRegisterAPIRoutes(aClassName: string; aService: TAPIService);
  911. const
  912. lRegisterCall = 'RegisterOpenAPIRoute(aBaseURL,''%s'',@%s,aUseStreaming);';
  913. var
  914. I: integer;
  915. lMethod: TAPIServiceMethod;
  916. lDecl, lEndPoint: string;
  917. begin
  918. Addln('class Procedure %s.RegisterAPIRoutes(aBaseURL : String; aUseStreaming : Boolean = False);', [aClassName]);
  919. Addln('begin');
  920. Indent;
  921. for I:=0 to aService.MethodCount-1 do
  922. begin
  923. lMethod:=aService.Methods[i];
  924. lDecl:=GetMethodHandleRequestName(lMethod, '');
  925. lEndPoint:=ConvertToRouteParams(lMethod.Path.PathComponent);
  926. Addln(lRegisterCall, [lEndPoint, lDecl]);
  927. end;
  928. Undent;
  929. Addln('end;');
  930. Addln('');
  931. end;
  932. procedure TServerModuleHandlerCodeGen.WriteConvertArgument(aMethod: TAPIServiceMethod;
  933. aParam: TAPIServiceMethodParam);
  934. const
  935. LocationNames: array[TParamLocation] of string =
  936. ('alQuery', 'alPath', 'alHeader', 'alCookie');
  937. var
  938. lDefault: string;
  939. lLocation: string;
  940. lLocalName: string;
  941. lParamName: string;
  942. begin
  943. lParamName:=aParam.OriginalName;
  944. lLocalName:='_'+aParam.Name;
  945. lDefault:=aParam.DefaultValue;
  946. if lDefault = '' then
  947. case aParam.ArgType of
  948. ptString: lDefault:='''''';
  949. ptInteger: lDefault:='0';
  950. ptInt64: lDefault:='Int64(0)';
  951. ptDateTime: lDefault:='TDateTime(0.0)';
  952. ptFloat32: lDefault:='0.0';
  953. ptFloat64: lDefault:='0.0';
  954. end;
  955. lLocation:=LocationNames[aParam.Location];
  956. AddLn('%s:=ExtractRequestArgument(aRequest,%s,''%s'',%s);',
  957. [lLocalName, lLocation, lParamName, lDefault]);
  958. end;
  959. procedure TServerModuleHandlerCodeGen.GenerateServerServiceHandleMethodImpl(lMethod: TAPIserviceMethod; const aClassName: string);
  960. var
  961. lResultType: string;
  962. lCallArgs: string;
  963. i: integer;
  964. procedure AddToArgs(aName: string);
  965. begin
  966. if lCallArgs<>'' then
  967. lCallargs:=lCallArgs+';';
  968. lCallargs:=lCallArgs+aName;
  969. end;
  970. begin
  971. AddLn(GetServerServiceHandleMethodDecl(lMethod, aClassName));
  972. lResultType:=lMethod.ResultDtoType;
  973. Addln('');
  974. Addln('var');
  975. indent;
  976. Addln('lResult : %s;', [lResultType]);
  977. for I:=0 to lMethod.ParamCount-1 do
  978. begin
  979. Addln('_%s;', [GetMethodParameterDecl(lMethod, lMethod.Param[i])]);
  980. AddToArgs('_'+lMethod.Param[I].Name);
  981. end;
  982. if lMethod.RequestBodyDataType<>nil then
  983. begin
  984. Addln('_Body : %s;', [lMethod.RequestBodyDataType.PascalName]);
  985. AddToArgs('_lBody');
  986. end;
  987. undent;
  988. Addln('');
  989. Addln('begin');
  990. indent;
  991. Addln('lResult:=Default(%s);', [lResultType]);
  992. Addln('try');
  993. Indent;
  994. Addln('if PrepareRequest(aRequest,aResponse) then');
  995. Indent;
  996. Addln('begin');
  997. if lResultType<>'' then
  998. begin
  999. for I:=0 to lMethod.ParamCount-1 do
  1000. WriteConvertArgument(lMethod, lMethod.Param[i]);
  1001. if lMethod.RequestBodyDataType<>nil then
  1002. AddLn('_lBody:=%s.Deserialize;', [lMethod.RequestBodyDataType.PascalName]);
  1003. Addln('lResult:=%s(%s);', [lMethod.MethodName, lCallArgs]);
  1004. if WriteClassType then
  1005. begin
  1006. Addln('try');
  1007. Indent;
  1008. Addln('aResponse.Content:=lResult.Serialize;');
  1009. end;
  1010. end
  1011. else
  1012. Addln('%s;', [lMethod.MethodName]);
  1013. if (lResultType<>'') and WriteClassType then
  1014. begin
  1015. Undent;
  1016. Addln('finally');
  1017. Indent;
  1018. Addln('FreeAndNil(lResult);');
  1019. Undent;
  1020. Addln('end;'); // Finally
  1021. end;
  1022. Addln('end;'); // if PrepareRequest
  1023. Undent;
  1024. Addln('ProcessResponse(aRequest,aResponse);');
  1025. Undent;
  1026. Addln('except');
  1027. Indent;
  1028. Addln('on E : Exception do');
  1029. Indent;
  1030. Addln('HandleRequestError(E,aRequest,aResponse);');
  1031. Undent;
  1032. Undent;
  1033. Addln('end;'); // except
  1034. undent;
  1035. Addln('end;'); // handlerequest
  1036. Addln('');
  1037. end;
  1038. procedure TServerCodeGen.GenerateServerServiceMethodImpl(lMethod: TAPIserviceMethod; const aClassName: string);
  1039. var
  1040. lResultType, lDecl: string;
  1041. begin
  1042. lDecl:=GetServerServiceMethodDecl(lMethod, aClassName);
  1043. lResultType:=lMethod.ResultDtoType;
  1044. AddLn(lDecl);
  1045. Addln('');
  1046. Addln('begin');
  1047. Indent;
  1048. AddLn('Result:=Default(%s);', [lResultType]);
  1049. Undent;
  1050. Addln('end;');
  1051. Addln('');
  1052. end;
  1053. procedure TServerCodeGen.GenerateServerServiceImplementationImpl(aService: TAPIService; const aModuleName: string; isAbstract: boolean);
  1054. var
  1055. lMethod: TAPIServiceMethod;
  1056. I: integer;
  1057. begin
  1058. AddLn('');
  1059. if not IsAbstract then
  1060. begin
  1061. for I:=0 to aService.MethodCount-1 do
  1062. begin
  1063. lMethod:=aService.Methods[i];
  1064. GenerateServerServiceMethodImpl(lMethod, aModuleName);
  1065. end;
  1066. AddLn('');
  1067. end;
  1068. end;
  1069. function TServerModuleHandlerCodeGen.GetModuleParentCLass: string;
  1070. begin
  1071. Result:=FModuleParentClass;
  1072. if Result = '' then
  1073. Result:='TFPOpenAPIModule';
  1074. end;
  1075. function TServerCodeGen.GetModuleParentUnit: string;
  1076. begin
  1077. Result:=FModuleParentUnit;
  1078. if Result = '' then
  1079. Result:='fpopenapimodule';
  1080. end;
  1081. procedure TServerModuleHandlerCodeGen.GenerateServerServiceImplementationImpl(aService: TAPIService; const aModuleName: string; IsAbstract: boolean);
  1082. var
  1083. I: integer;
  1084. lMethod: TAPIServiceMethod;
  1085. begin
  1086. GenerateRegisterAPIRoutes(aModuleName, aService);
  1087. for I:=0 to aService.MethodCount-1 do
  1088. begin
  1089. lMethod:=aService.Methods[i];
  1090. GenerateServerServiceHandleMethodImpl(lMethod, aModuleName);
  1091. end;
  1092. inherited GenerateServerServiceImplementationImpl(aService, aModuleName, isAbstract);
  1093. end;
  1094. procedure TServerModuleHandlerCodeGen.Execute(aData: TAPIData);
  1095. var
  1096. I: integer;
  1097. lService: TAPIService;
  1098. lName: string;
  1099. begin
  1100. SetTypeData(aData);
  1101. GenerateHeader;
  1102. GenerateFPCDirectives();
  1103. Addln('unit %s;', [Self.OutputUnitName]);
  1104. Addln('');
  1105. if AsyncService then
  1106. GenerateFPCDirectives();
  1107. Addln('interface');
  1108. Addln('');
  1109. Addln('uses');
  1110. indent;
  1111. AddLn('%s, httpprotocol, httpdefs, fphttpapp, httproute, %s;',
  1112. [ModuleParentUnit, DtoUnit]);
  1113. undent;
  1114. Addln('');
  1115. EnsureSection(csType);
  1116. indent;
  1117. for I:=0 to aData.ServiceCount-1 do
  1118. begin
  1119. lService:=aData.Services[I];
  1120. if (Self.ServiceName = '') or SameText(lService.ServiceName, Self.ServiceName) then
  1121. begin
  1122. if AbstractServiceCalls then
  1123. lName:='TAbstract'+lService.ServiceName+'Module'
  1124. else
  1125. lName:='T'+lService.ServiceName+'Module';
  1126. GenerateServerServiceImplementationDecl(
  1127. lService, ModuleParentClass, lName, AbstractServiceCalls, True);
  1128. end;
  1129. end;
  1130. undent;
  1131. Addln('');
  1132. Addln('implementation');
  1133. Addln('');
  1134. Addln('uses');
  1135. indent;
  1136. if DelphiCode then
  1137. Addln('System.SysUtils')
  1138. else
  1139. Addln('SysUtils');
  1140. Addln(', %s;', [SerializerUnit]);
  1141. undent;
  1142. Addln('');
  1143. for I:=0 to aData.ServiceCount-1 do
  1144. begin
  1145. lService:=aData.Services[I];
  1146. if (Self.ServiceName = '') or SameText(lService.ServiceName, Self.ServiceName) then
  1147. begin
  1148. if AbstractServiceCalls then
  1149. lName:='TAbstract'+lService.ServiceName+'Module'
  1150. else
  1151. lName:='T'+lService.ServiceName+'Module';
  1152. GenerateServerServiceImplementationImpl(lService, lName, AbstractServiceCalls);
  1153. end;
  1154. end;
  1155. Addln('');
  1156. Addln('end.');
  1157. end;
  1158. { TServerImplementationModuleCodeGen }
  1159. procedure TServerImplementationModuleCodeGen.Execute(aData: TAPIData);
  1160. var
  1161. I: integer;
  1162. lService: TAPIService;
  1163. lName, lParentName: string;
  1164. begin
  1165. SetTypeData(aData);
  1166. GenerateHeader;
  1167. GenerateFPCDirectives();
  1168. Addln('unit %s;', [Self.OutputUnitName]);
  1169. Addln('');
  1170. if AsyncService then
  1171. GenerateFPCDirectives();
  1172. Addln('interface');
  1173. Addln('');
  1174. Addln('uses');
  1175. indent;
  1176. AddLn('%s, %s;', [ModuleParentUnit, DtoUnit]);
  1177. undent;
  1178. Addln('');
  1179. EnsureSection(csType);
  1180. indent;
  1181. for I:=0 to aData.ServiceCount-1 do
  1182. begin
  1183. lService:=aData.Services[I];
  1184. if (Self.ServiceName = '') or SameText(lService.ServiceName, Self.ServiceName) then
  1185. begin
  1186. lName:='T'+lService.ServiceName+'Module';
  1187. lParentName:='TAbstract'+lService.ServiceName+'Module';
  1188. GenerateServerServiceImplementationDecl(lService, lParentName, lName, False, False);
  1189. end;
  1190. end;
  1191. undent;
  1192. Addln('');
  1193. Addln('implementation');
  1194. Addln('');
  1195. Addln('uses');
  1196. indent;
  1197. if DelphiCode then
  1198. Addln('System.SysUtils')
  1199. else
  1200. Addln('SysUtils');
  1201. Addln(', %s;', [SerializerUnit]);
  1202. undent;
  1203. Addln('');
  1204. for I:=0 to aData.ServiceCount-1 do
  1205. begin
  1206. lService:=aData.Services[I];
  1207. if (Self.ServiceName = '') or SameText(lService.ServiceName, Self.ServiceName) then
  1208. begin
  1209. lName:='T'+lService.ServiceName+'Module';
  1210. GenerateServerServiceImplementationImpl(lService, lName, False);
  1211. end;
  1212. end;
  1213. Addln('');
  1214. Addln('end.');
  1215. end;
  1216. { TServerServiceModule }
  1217. function TServerProxyServiceModuleCodeGen.GetProxyVarName: String;
  1218. begin
  1219. Result:=FProxyVarName;
  1220. if Result='' then
  1221. Result:=Copy(ProxyClassName,2,Length(ProxyClassName)-1);
  1222. end;
  1223. procedure TServerProxyServiceModuleCodeGen.SetProxyClassName(const aValue: string);
  1224. begin
  1225. if FProxyClassName=aValue then Exit;
  1226. FProxyClassName:=aValue;
  1227. CheckDefaults;
  1228. end;
  1229. constructor TServerProxyServiceModuleCodeGen.Create(AOwner: TComponent);
  1230. begin
  1231. inherited Create(AOwner);
  1232. FForm:=TStringList.Create;
  1233. CheckDefaults;
  1234. end;
  1235. destructor TServerProxyServiceModuleCodeGen.Destroy;
  1236. begin
  1237. FreeAndNil(FForm);
  1238. inherited Destroy;
  1239. end;
  1240. procedure TServerProxyServiceModuleCodeGen.CheckDefaults;
  1241. begin
  1242. if FProxyClassName='' then
  1243. FProxyClassName:=DefaultServerProxyName;
  1244. if FProxyParentClass='' then
  1245. FProxyParentClass:=DefaultServerProxyParent;
  1246. if FProxyParentUnit='' then
  1247. FProxyParentUnit:=DefaultServerProxyParentUnit;
  1248. end;
  1249. procedure TServerProxyServiceModuleCodeGen.GenerateModule;
  1250. var
  1251. I: integer;
  1252. lClass,lUnits : String;
  1253. lService: TAPIService;
  1254. begin
  1255. GenerateFPCDirectives();
  1256. CheckDefaults;
  1257. Addln('unit %s;', [Self.OutputUnitName]);
  1258. Addln('');
  1259. Addln('interface');
  1260. Addln('');
  1261. Addln('uses');
  1262. indent;
  1263. lUnits:=ServiceInterfaceUnit+', '+ServiceImplementationUnit;
  1264. if not (SameText(ProxyParentUnit,'Classes') or SameText(ProxyParentUnit,'System.Classes')) then
  1265. if DelphiCode then
  1266. lUnits:='System.Classes, '+lUnits
  1267. else
  1268. lUnits:='Classes, fpWebClient, '+lUnits;
  1269. AddLn('%s, %s;', [ProxyParentUnit, lUnits]);
  1270. undent;
  1271. Addln('');
  1272. EnsureSection(csType);
  1273. indent;
  1274. Addln('%s = class(%s)',[ProxyClassName,ProxyParentClass]);
  1275. Addln('private');
  1276. indent;
  1277. Addln('FWebClient : TAbstractWebClient;');
  1278. Addln('FBaseURL : TAbstractWebClient;');
  1279. for I:=0 to APIData.ServiceCount-1 do
  1280. begin
  1281. lService:=APIData.Services[I];
  1282. lClass:=lService.ServiceProxyImplementationClassName;
  1283. Addln('F%s : %s;',[lService.ServiceName,lClass]);
  1284. end;
  1285. if UseInterfaceType then
  1286. for I:=0 to APIData.ServiceCount-1 do
  1287. begin
  1288. lService:=APIData.Services[I];
  1289. lClass:=lService.ServiceProxyImplementationClassName;
  1290. Addln('function Get%s : %s;',[lService.ServiceName,lService.ServiceInterfaceName]);
  1291. end;
  1292. Addln('Procedure SetBaseURL(const aValue : string);');
  1293. undent;
  1294. Addln('protected');
  1295. indent;
  1296. Addln('Procedure CreateServices; virtual;');
  1297. undent;
  1298. Addln('public');
  1299. indent;
  1300. Addln('constructor Create(aOwner : TComponent); override;');
  1301. for I:=0 to APIData.ServiceCount-1 do
  1302. begin
  1303. lService:=APIData.Services[I];
  1304. if UseInterfaceType then
  1305. Addln('Property %s : %s read Get%s;',[lService.ServiceName,lService.ServiceInterfaceName,lService.ServiceName])
  1306. else
  1307. Addln('Property %s : %s read F%s;',[lService.ServiceName,lService.ServiceProxyImplementationClassName,lService.ServiceName]);
  1308. end;
  1309. Addln('Property BaseURL : String Read FBaseURL Write SetBaseURL;',[lService.ServiceName,lService.ServiceInterfaceName,lService.ServiceName]);
  1310. undent;
  1311. Addln('end;');
  1312. undent;
  1313. Addln('');
  1314. if FormFile then
  1315. begin
  1316. Addln('var %s : %s;',[ProxyVarName,ProxyClassName]);
  1317. Addln('');
  1318. end;
  1319. Addln('implementation');
  1320. Addln('');
  1321. Addln('uses');
  1322. indent;
  1323. if DelphiCode then
  1324. Addln('System.SysUtils;')
  1325. else
  1326. Addln('SysUtils;');
  1327. undent;
  1328. if FormFile then
  1329. begin
  1330. Addln('');
  1331. Addln('{$R *.lfm}');
  1332. end;
  1333. Addln('');
  1334. Addln('constructor %s.Create(aOwner : TComponent);',[ProxyClassName]);
  1335. Addln('');
  1336. Addln('begin');
  1337. indent;
  1338. Addln('Inherited;');
  1339. Addln('FWebClient:=DefaultWebClientClass.Create(Self);');
  1340. Addln('CreateServices;');
  1341. undent;
  1342. Addln('end;');
  1343. Addln('');
  1344. Addln('');
  1345. Addln('procedure %s.CreateServices;',[ProxyClassName]);
  1346. Addln('');
  1347. Addln('begin');
  1348. Indent;
  1349. for I:=0 to APIData.ServiceCount-1 do
  1350. begin
  1351. lService:=APIData.Services[I];
  1352. lClass:=lService.ServiceProxyImplementationClassName;
  1353. Addln('F%s:=%s.create(Self);',[lService.ServiceName,lClass]);
  1354. Addln('%s(F%s).WebClient:=FWebClient',[lClass,lService.ServiceName]);
  1355. end;
  1356. undent;
  1357. Addln('end;');
  1358. Addln('');
  1359. Addln('');
  1360. Addln('Procedure %s.SetBaseURL(const aValue : string);',[ProxyClassName]);
  1361. Addln('');
  1362. Addln('begin');
  1363. Indent;
  1364. Addln('FBaseURL:=aValue;');
  1365. for I:=0 to APIData.ServiceCount-1 do
  1366. begin
  1367. lService:=APIData.Services[I];
  1368. Addln('F%s.BaseURL:=aValue;',[lService.ServiceName]);
  1369. end;
  1370. undent;
  1371. Addln('end;');
  1372. Addln('');
  1373. Addln('');
  1374. for I:=0 to APIData.ServiceCount-1 do
  1375. begin
  1376. lService:=APIData.Services[I];
  1377. lClass:=lService.ServiceProxyImplementationClassName;
  1378. Addln('function %s.Get%s : %s;',[ProxyClassName,lService.ServiceName,lService.ServiceInterfaceName]);
  1379. Addln('');
  1380. Addln('begin');
  1381. Indent;
  1382. Addln('Result:=F%s;',[lService.ServiceName]);
  1383. Undent;
  1384. Addln('end;');
  1385. Addln('');
  1386. Addln('');
  1387. end;
  1388. Addln('');
  1389. Addln('end.');
  1390. end;
  1391. procedure TServerProxyServiceModuleCodeGen.GenerateFormFile;
  1392. begin
  1393. With FForm Do
  1394. begin
  1395. Add('object %s: %s',[ProxyVarName,ProxyClassName]);
  1396. Add(' OldCreateOrder = False');
  1397. Add(' Height = 150');
  1398. Add(' HorizontalOffset = 547');
  1399. Add(' VerticalOffset = 323');
  1400. Add(' Width = 150');
  1401. Add('end');
  1402. end;
  1403. end;
  1404. procedure TServerProxyServiceModuleCodeGen.Execute(aData: TAPIData);
  1405. begin
  1406. SetTypeData(aData);
  1407. GenerateModule;
  1408. if FFormFile then
  1409. GenerateFormFile;
  1410. end;
  1411. end.