googlediscoverytopas.pp 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100
  1. { Base Google API code generator
  2. Copyright (C) 2015 Michael Van Canneyt [email protected]
  3. This library is free software; you can redistribute it and/or modify it
  4. under the terms of the GNU Library General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or (at your
  6. option) any later version with the following modification:
  7. As a special exception, the copyright holders of this library give you
  8. permission to link this library with independent modules to produce an
  9. executable, regardless of the license terms of these independent modules,and
  10. to copy and distribute the resulting executable under terms of your choice,
  11. provided that you also meet, for each linked independent module, the terms
  12. and conditions of the license of that module. An independent module is a
  13. module which is not derived from or based on this library. If you modify
  14. this library, you may extend this exception to your version of the library,
  15. but you are not obligated to do so. If you do not wish to do so, delete this
  16. exception statement from your version.
  17. This program is distributed in the hope that it will be useful, but WITHOUT
  18. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  19. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
  20. for more details.
  21. You should have received a copy of the GNU Library General Public License
  22. along with this library; if not, write to the Free Software Foundation,
  23. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  24. }
  25. unit googlediscoverytopas;
  26. {$mode objfpc}{$H+}
  27. interface
  28. uses
  29. typinfo, Classes, SysUtils, fpjson, restcodegen, restbase, googlebase;
  30. Type
  31. TTypeDef = Class;
  32. TSchema = Class;
  33. TSchemas = Array of TSchema;
  34. TPropertyDef = Class;
  35. TProperties = TSchemas;
  36. TRestMethod = Class;
  37. TRestMethods = Array of TRestMethod;
  38. TArrayPropertyDef = Class;
  39. { TIcons }
  40. TGoogleIcons = Class(TGoogleBaseObject)
  41. private
  42. Fx16: String;
  43. Fx32: String;
  44. Published
  45. Property x16 : String Read Fx16 Write fx16;
  46. Property x32 : String Read Fx32 Write fx32;
  47. end;
  48. { TGoogleAuth2 }
  49. TGoogleAuth2 = Class(TGoogleBaseObject)
  50. private
  51. FScopes: TSchemas;
  52. Protected
  53. {$ifdef ver2_6}
  54. Procedure SetArrayLength(const AName : String; ALength : Longint); override;
  55. {$endif}
  56. Published
  57. Property Scopes : TSchemas Read Fscopes Write Fscopes;
  58. end;
  59. { TGoogleAuth }
  60. TGoogleAuth = Class(TGoogleBaseObject)
  61. private
  62. Foauth2: TGoogleAuth2;
  63. Published
  64. Property oauth2 : TGoogleAuth2 Read Foauth2 Write Foauth2;
  65. end;
  66. { TDiscoveryJSONToPas }
  67. { TArrayPropertyDef }
  68. { TAnnotations }
  69. TAnnotations = Class(TGoogleBaseObject)
  70. private
  71. FRequired: TStringArray;
  72. Protected
  73. {$ifdef ver2_6}
  74. Procedure SetArrayLength(const AName : String; ALength : Longint); override;
  75. {$endif}
  76. Published
  77. Property required : TStringArray Read FRequired Write Frequired;
  78. end;
  79. { TSchema }
  80. TSchema = Class(TGoogleBaseObject)
  81. private
  82. FadditionalProperties: TSchema;
  83. FAnnotations: TAnnotations;
  84. FDefault: String;
  85. Fdescription: string;
  86. fdivisibleby: integer;
  87. FEnum: TJSONSchema;
  88. FenumDescriptions: TStringArray;
  89. fexclusivemaximum: boolean;
  90. fexclusiveminimum: boolean;
  91. Fextends: string;
  92. FFormat: string;
  93. fitems: TSchema;
  94. fmaximum: integer;
  95. fmaxItems: integer;
  96. fmaxlength: integer;
  97. Fmethods: TRestMethods;
  98. fminimum: integer;
  99. fminItems: integer;
  100. fminlength: integer;
  101. FName: String;
  102. FPattern: string;
  103. FProperties: TProperties;
  104. FPropertyName: String;
  105. FreadOnly: Boolean;
  106. Fref: string;
  107. FRefSchema: TSchema;
  108. frequired: Boolean;
  109. FResources: TSchemas;
  110. Fschema: String;
  111. FType: string;
  112. FID: String;
  113. FTypeDef: TTypeDef;
  114. FTypeName: String;
  115. funiqueItems: boolean;
  116. FVariant: TJSONSchema;
  117. function DoGetTypeName(PrependT: Boolean): String;
  118. function GetTypeName: String;
  119. Public
  120. Class function BaseType(ATypeName: String): Boolean;
  121. Class function GetBaseTypeName(AType,AFormat : String) : string;
  122. {$ifdef ver2_6}
  123. Procedure SetArrayLength(const AName : String; ALength : Longint); override;
  124. {$endif}
  125. Function DebugName : String;
  126. function GetBaseTypeName : string;
  127. Function BaseType : Boolean;
  128. Function ClassProperties : TProperties;
  129. Property PropertyName : String Read FPropertyName Write FPropertyName;
  130. Property TypeName : String Read GetTypeName Write FTypeName;
  131. Property Refschema : TSchema Read FRefSchema Write FRefSchema;
  132. Property TypeDef : TTypeDef Read FTypeDef write FTypeDef;
  133. Published
  134. Property id : String Read FID Write FID;
  135. Property description : string read Fdescription Write Fdescription;
  136. Property _type : String Read FType Write FType;
  137. Property ref : String Read FRef Write FRef;
  138. Property schema: String Read Fschema Write Fschema;
  139. Property name : String Read FName Write FName;
  140. Property enum : TJSONSchema Read FEnum Write FEnum;
  141. Property enumDescriptions : TStringArray Read FenumDescriptions Write FenumDescriptions;
  142. Property properties : TProperties Read FProperties Write FProperties;
  143. Property items : TSchema Read fitems write fitems;
  144. Property default : String Read FDefault Write FDefault;
  145. property required : Boolean read frequired write frequired;
  146. Property annotations : TAnnotations Read FAnnotations Write FAnnotations;
  147. Property format : string Read FFormat Write FFormat;
  148. Property additionalProperties : TSchema Read FadditionalProperties Write FadditionalProperties;
  149. Property minLength : integer read fminlength write fminlength;
  150. Property maxLength : integer read fmaxlength write fmaxlength;
  151. Property minItems : integer read fminItems write fminItems;
  152. Property maxItems : integer read fmaxItems write fmaxItems;
  153. Property minimum : integer read fminimum write fminimum;
  154. Property pattern : string read FPattern write fPattern;
  155. Property exclusiveMaximum : boolean read fexclusivemaximum write fexclusivemaximum;
  156. Property exclusiveMinimum : boolean read fexclusiveminimum write fexclusiveminimum;
  157. Property uniqueItems : boolean read funiqueItems write funiqueItems;
  158. Property maximum : integer read fmaximum write fmaximum;
  159. Property divisibleBy : integer read fdivisibleby write fdivisibleby;
  160. Property extends : string Read Fextends Write Fextends;
  161. Property methods : TRestMethods Read Fmethods Write Fmethods;
  162. property readOnly : Boolean Read FreadOnly Write fReadOnly;
  163. Property resources : TSchemas Read FResources write FResources;
  164. Property variant : TJSONSchema Read FVariant Write FVariant;
  165. end;
  166. TArrayPropertyDef = Class(TSchema);
  167. TPropertyDef = Class(TSchema);
  168. TMediaUploadprotocolssimple = Class(TGoogleBaseObject)
  169. Private
  170. Fmultipart : boolean;
  171. Fpath : string;
  172. Published
  173. Property multipart : boolean Read Fmultipart Write Fmultipart;
  174. Property path : string Read Fpath Write Fpath;
  175. end;
  176. TMediaUploadProtocolsSimpleArray = Array of TMediaUploadProtocolsSimple;
  177. TMediaUploadProtocolsResumable = Class(TGoogleBaseObject)
  178. Private
  179. Fmultipart : boolean;
  180. Fpath : string;
  181. Published
  182. Property multipart : boolean Read Fmultipart Write Fmultipart;
  183. Property path : string Read Fpath Write Fpath;
  184. end;
  185. TMediaUploadProtocolsResumableArray = Array of TMediaUploadProtocolsResumable;
  186. { TMediaUploadProtocols }
  187. TMediaUploadProtocols = Class(TGoogleBaseObject)
  188. private
  189. Fresumable: TMediaUploadprotocolsresumable;
  190. Fsimple: TMediaUploadprotocolssimple;
  191. Published
  192. Property resumable : TMediaUploadprotocolsresumable Read Fresumable Write Fresumable;
  193. Property simple : TMediaUploadprotocolssimple Read Fsimple Write Fsimple;
  194. end;
  195. TMediaUploadProtocolsArray = Array of TMediaUploadProtocols;
  196. TMediaUpload = Class(TGoogleBaseObject)
  197. private
  198. FAccept: TStringArray;
  199. FMaxSize: String;
  200. Fprotocols: TMediaUploadProtocols;
  201. protected
  202. {$ifdef ver2_6}
  203. Procedure SetArrayLength(const AName : String; ALength : Longint); override;
  204. {$endif}
  205. Published
  206. Property Accept : TStringArray Read FAccept Write FAccept;
  207. property MaxSize : String Read FMaxSize Write FMaxSize;
  208. Property protocols : TMediaUploadProtocols Read Fprotocols Write Fprotocols;
  209. end;
  210. { TRequest }
  211. TRequest = Class(TGoogleBaseObject)
  212. private
  213. fparameterName: string;
  214. fref: string;
  215. Published
  216. Property ref : string read fref write fref;
  217. Property parameterName : string read fparameterName write fparameterName;
  218. end;
  219. { TResponse }
  220. TResponse = Class(TGoogleBaseObject)
  221. private
  222. fref: string;
  223. Published
  224. Property ref : string read fref write fref;
  225. end;
  226. { TRestMethodParam }
  227. TRestMethodParam = Class(TSchema)
  228. private
  229. FLocation: string;
  230. FRepeated: boolean;
  231. FSourceName: String;
  232. Public
  233. Property SourceName : String Read FSourceName Write FSourceName;
  234. Published
  235. Property location : string Read FLocation Write FLocation;
  236. Property repeated : boolean Read FRepeated write FRepeated;
  237. end;
  238. TRestMethodParams = Array of TRestMethodParam;
  239. { TRestMethod }
  240. TRestMethod = Class(TGoogleBaseObject)
  241. private
  242. FDescription: String;
  243. FeTagrequired: Boolean;
  244. FflatPath: string;
  245. FhttpMethod: string;
  246. Fid: string;
  247. fMediaUpload: TMediaUpload;
  248. fname: string;
  249. FParameterOrder: TStringArray;
  250. fparameters: TRestMethodParams;
  251. fpath: string;
  252. frequest: trequest;
  253. fresponse: tresponse;
  254. Fscopes: TStringArray;
  255. FsupportsMediaDownload: Boolean;
  256. FsupportsMediaUpload: Boolean;
  257. FsupportsSubscription: Boolean;
  258. protected
  259. {$ifdef ver2_6}
  260. Procedure SetArrayLength(const AName : String; ALength : Longint); override;
  261. {$endif}
  262. Published
  263. Property name : string read fname Write fname;
  264. Property description : String Read FDescription Write FDescription;
  265. Property etagRequired: Boolean read FeTagrequired write FeTagrequired;
  266. Property httpMethod: string read FhttpMethod write FhttpMethod;
  267. Property id : string read Fid Write fID;
  268. Property MediaUpload : TMediaUpload Read fMediaUpload Write fmediaUpload;
  269. Property parameterOrder : TStringArray Read FParameterOrder Write FParameterOrder;
  270. Property parameters : TRestMethodParams read fparameters write fparameters;
  271. Property path : string read fpath Write fpath;
  272. Property flatPath : string read FflatPath Write FflatPath;
  273. Property request : trequest read frequest write frequest;
  274. Property response : tresponse read fresponse write fresponse;
  275. property scopes : TStringArray Read Fscopes write Fscopes;
  276. property supportsMediaDownload : Boolean Read FsupportsMediaDownload Write FsupportsMediaDownload;
  277. property supportsMediaUpload : Boolean Read FsupportsMediaUpload Write FsupportsMediaUpload;
  278. property supportsSubscription : Boolean Read FsupportsSubscription Write FsupportsSubscription;
  279. end;
  280. { TGoogleRestDescription }
  281. TGoogleRestDescription = Class(TGoogleBaseObject)
  282. private
  283. Fauth: TGoogleAuth;
  284. fbasePath: string;
  285. fbaseURL: string;
  286. fbatchPath: string;
  287. FCanonicalName: String;
  288. FDescription: string;
  289. FdiscoveryVersion: String;
  290. FdocumentationLink: string;
  291. FEtag: String;
  292. Ffeatures: TstringArray;
  293. Ficons: TGoogleIcons;
  294. fid: String;
  295. FKind: String;
  296. Flabels: TstringArray;
  297. Fmethods: TRestMethods;
  298. Fname: String;
  299. fOwnerDomain: String;
  300. fOwnerName: String;
  301. FpackagePath: String;
  302. Fparameters: TJSONSchema;
  303. Fprotocol: string;
  304. FResources: TSchemas;
  305. FRevision: string;
  306. frootURL: string;
  307. FSchemas: TSchemas;
  308. fservicePath: string;
  309. FTitle: string;
  310. Fversion: String;
  311. Protected
  312. {$ifdef ver2_6}
  313. Procedure SetArrayLength(const AName : String; ALength : Longint); override;
  314. {$endif}
  315. Public
  316. Published
  317. property Auth : TGoogleAuth Read Fauth Write Fauth;
  318. property basePath : string read fbasePath write FbasePath;
  319. property baseUrl : string read fbaseURL write FbaseURL;
  320. property batchPath : string read fbatchPath write FbatchPath;
  321. Property canonicalName : String Read FCanonicalName Write FCanonicalName;
  322. Property description : string Read FDescription Write FDescription;
  323. Property discoveryVersion : String Read FdiscoveryVersion Write FdiscoveryVersion;
  324. Property documentationLink : string read FdocumentationLink Write FdocumentationLink;
  325. Property etag : String Read FEtag Write FEtag;
  326. Property features : TstringArray Read Ffeatures Write Ffeatures;
  327. property icons : TGoogleIcons Read Ficons Write Ficons;
  328. Property id: String Read fid Write Fid;
  329. Property kind: String Read FKind Write FKind;
  330. Property labels : TstringArray Read Flabels Write Flabels;
  331. Property methods : TRestMethods Read Fmethods Write Fmethods;
  332. Property name : String Read Fname Write Fname;
  333. Property ownerDomain : String Read fOwnerDomain Write FOwnerDomain;
  334. Property ownerName : String Read fOwnerName Write FOwnerName;
  335. Property packagePath : String Read FpackagePath Write FpackagePath;
  336. Property parameters : TJSONSchema Read Fparameters Write FParameters;
  337. property protocol : string Read Fprotocol write FProtocol;
  338. Property resources : TSchemas Read FResources write FResources;
  339. Property revision : string Read FRevision Write FRevision;
  340. property rootUrl : string read frootURL write FrootURL;
  341. property schemas : TSchemas read FSchemas write fschemas;
  342. property servicePath : string read fservicePath write FservicePath;
  343. Property title : string Read FTitle Write FTitle;
  344. Property version : String Read Fversion Write Fversion;
  345. end;
  346. TParamLocation = (plPath,plQuery);
  347. TParamLocations = Set of TParamLocation;
  348. TDataType = (dtalias,dtClass,dtarray);
  349. { TTypeDef }
  350. TTypeDef = Class(TCollectionItem)
  351. private
  352. FDataType: TDataType;
  353. FItemSchema: TSchema;
  354. FPascalName: String;
  355. FSchema: TSchema;
  356. FTopLevel: Boolean;
  357. Public
  358. Property PascalName : String Read FPascalName Write FPascalName;
  359. Property Schema : TSchema Read FSchema Write FSchema;
  360. Property DataType : TDataType Read FDataType Write FDataType;
  361. Property ItemSchema: TSchema Read FItemSchema Write FItemSchema;
  362. Property TopLevel : Boolean Read FTopLevel Write FTopLevel;
  363. end;
  364. { TTypeDefEnumerator }
  365. TTypeDefEnumerator = Class(TCollectionEnumerator)
  366. Public
  367. Function GetCurrent: TTypeDef;
  368. property Current: TTypeDef read GetCurrent;
  369. end;
  370. { TTypeDefs }
  371. TTypeDefs = Class(TCollection)
  372. private
  373. function GetD(AIndex : Integer): TTypeDef;
  374. Public
  375. Function GetEnumerator: TTypeDefEnumerator;
  376. Function IndexOf(ATypename : String) : Integer;
  377. Function Find(ATypename : String) : TTypeDef;
  378. Function AddTypeDef(ADataType : TDataType; APascalName : String; ASchema : TSchema) : TTypeDef;
  379. Property Defs[AIndex : Integer] : TTypeDef Read GetD; Default;
  380. end;
  381. TGoogleCodeOption = (gcoUseListForArray,gcoFlatResources);
  382. TGoogleCodeOptions = Set of TGoogleCodeOption;
  383. TDiscoveryJSONToPas = Class(TRestCodeGenerator)
  384. private
  385. FArrayItemSuffix: String;
  386. FCodeOptions: TGoogleCodeOptions;
  387. FDescription: TGoogleRestDescription;
  388. FPropertyTypeSuffix: String;
  389. FResourceSuffix: String;
  390. FTypes : TTypeDefs;
  391. Function AddType(ASchema: TSchema; NamePrefix: String; IsTopLevel : Boolean) : TTypeDef;
  392. procedure CollectType(S: TSchema; NamePrefix: String; IsTopLevel : Boolean);
  393. function GetFlat: Boolean;
  394. function GetSchemaDataType(S: TSchema): TDataType;
  395. function GetUseListForArray: Boolean;
  396. function ReservedMethod(ANAme: String): boolean;
  397. Protected
  398. procedure AssignParamNames(Res: TSchema; M: TRestMethod); virtual;
  399. Function BaseUnits : String; override;
  400. // Global functions
  401. Function GetPropertyType(AClassName: String; ASchema: TSchema): String;
  402. Procedure CollectTypes;
  403. Procedure CollectTypes(Schemas: TSchemas; NamePrefix : String);
  404. Procedure ResolveRefs;
  405. Procedure CreateInterface;
  406. Procedure CreateImplementation;
  407. // Schema Classes
  408. procedure CreateSetArrayLength(AClassName: String; ASchema, AItemSchema: TSchema);
  409. procedure CreateExportPropertyName(AClassName: String; ASchema, AItemSchema: TSchema);
  410. Procedure CreateClassDeclaration(AClassName: String; ASchema: TSchema);
  411. Procedure CreateArrayClassDeclaration(AClassName: String; ASchema,AItemSchema: TSchema);
  412. Procedure CreateClassImplementation(AClassName: String; ASchema,AItemSchema: TSchema);
  413. Procedure CreateArrayClassImplementation(AClassName: String; ASchema,AItemSchema: TSchema);
  414. Procedure CreateArrayClassEnumeratorImplementation(AClassName: String; ASchema,AItemSchema: TSchema);
  415. // API class
  416. Function GetAPIClassName: String;
  417. Procedure CreateAPIClassDeclaration;
  418. Procedure CreateAPIClassImplementation;
  419. // Resource classes
  420. Function ConstructResourcePrefix(Const APrefix: String; AResource: TSchema ): String;
  421. // Recursive calls
  422. Procedure CreateResourceClassImplementations(Const APrefix: String; Resources: TSchemas);
  423. Procedure CreateResourceAPIFunctionImplementations(Const AClassName: String; Const APrefix: String; Resources: TSchemas); virtual;
  424. Procedure CreateResourceInstanceFields(Const APrefix: String; Resources: TSchemas);
  425. Procedure CreateResourceInstanceGetters(Const APrefix: String; Resources: TSchemas);
  426. Procedure CreateResourceAPI(Const APrefix: String; Resources: TSchemas);
  427. Procedure CreateResourceProperties(Const APrefix: String; Resources: TSchemas);
  428. Function GetResourceClassName(Const APrefix : String; Res: TSchema): String;
  429. procedure CreateResourceDeclarations(Const APrefix: String; Resources: TSchemas);
  430. Procedure CreateResourceClassDeclaration(Const APrefix: String; Res: TSchema);
  431. Procedure CreateResourceClassImplementation(Const APrefix: String; Res: TSchema);
  432. Procedure CreateResourceClassMethodsImplementation(Res: TSchema; Const AClassName: String);
  433. Procedure CreateResourceMethodImplementation(AClassName: String; Res: TSchema; M: TRestMethod); // Query version
  434. Procedure CreateResourceMethodImplementationOptions(Const APrefix,
  435. AClassName: String; Res: TSchema; M: TRestMethod);// Options record version
  436. Function GetResourceMethodSignature(M: TRestmethod; Out IsFunction: Boolean; QueryOptionType : String; AddTypes : Boolean = True): String;
  437. Function DescribeMethodParams(M: TRestMethod): TParamLocations;
  438. Function HavePathParams(M: TRestMethod): Boolean;
  439. Function HaveQueryParams(M: TRestMethod): Boolean;
  440. Procedure CreateResourceMethodQueryParams(APrefix: String; Res: TSchema;
  441. M: TRestMethod);
  442. Public
  443. Constructor Create(AOwner : TComponent); override;
  444. Destructor Destroy; override;
  445. Procedure LoadFromStream(Const AStream : TStream); override;
  446. Procedure LoadFromJSON(Const JSON : TJSONObject); virtual;
  447. Procedure Execute; override;
  448. Class Procedure RegisterAllObjects;
  449. Property APIClassName: String Read GetAPIClassName;
  450. Property UseListForArray : Boolean Read GetUseListForArray;
  451. Property FlatResources : Boolean Read GetFlat;
  452. Published
  453. Property Description : TGoogleRestDescription Read FDescription;
  454. Property ResourceSuffix : String Read FResourceSuffix Write FResourceSuffix;
  455. Property ArrayItemSuffix : String Read FArrayItemSuffix Write FArrayItemSuffix;
  456. Property PropertyTypeSuffix : String Read FPropertyTypeSuffix Write FPropertyTypeSuffix;
  457. Property CodeOptions : TGoogleCodeOptions Read FCodeOptions Write FCodeOptions;
  458. end;
  459. implementation
  460. { TGoogleRestDescription }
  461. {$IFDEF VER_2_6}
  462. Procedure TGoogleRestDescription.SetArrayLength(const AName: String;
  463. ALength: Longint);
  464. begin
  465. case aname of
  466. 'schemas' : setlength(FSchemas,ALength);
  467. 'features' : setlength(FFeatures,ALength);
  468. 'labels' : setlength(FLabels,ALength);
  469. 'methods' : setlength(Fmethods,ALength);
  470. 'resources' : setlength(FResources,ALength);
  471. else
  472. inherited SetArrayLength(AName, ALength);
  473. end;
  474. end;
  475. {$ENDIF}
  476. { TRestMethod }
  477. {$ifdef ver2_6}
  478. Procedure TRestMethod.SetArrayLength(const AName: String; ALength: Longint);
  479. begin
  480. case AName of
  481. 'parameterorder' : SetLength(FParameterOrder,ALength);
  482. 'parameters' : SetLength(FParameters,ALength);
  483. 'scopes' : SetLength(FScopes,ALength);
  484. else
  485. inherited SetArrayLength(AName, ALength);
  486. end;
  487. end;
  488. { TMediaUpload }
  489. Procedure TMediaUpload.SetArrayLength(const AName: String; ALength: Longint);
  490. begin
  491. Case AName of
  492. 'accept' : SetLength(FAccept,ALength);
  493. else
  494. inherited SetArrayLength(AName, ALength);
  495. end;
  496. end;
  497. { TGoogleAuth2 }
  498. Procedure TGoogleAuth2.SetArrayLength(const AName: String; ALength: Longint);
  499. begin
  500. Case AName of
  501. 'scopes' : SetLength(FScopes,ALength);
  502. else
  503. inherited SetArrayLength(AName, ALength);
  504. end;
  505. end;
  506. { TAnnotations }
  507. Procedure TAnnotations.SetArrayLength(const AName: String; ALength: Longint);
  508. begin
  509. Case AName of
  510. 'required' :SetLength(FRequired,ALength);
  511. else
  512. inherited SetArrayLength(AName, ALength);
  513. end;
  514. end;
  515. {$endif}
  516. { TTypeDefEnumerator }
  517. function TTypeDefEnumerator.GetCurrent: TTypeDef;
  518. begin
  519. Result:=(Inherited GetCurrent) as TTypeDef;
  520. end;
  521. { TTypeDefs }
  522. function TTypeDefs.GetD(AIndex : Integer): TTypeDef;
  523. begin
  524. Result:=Items[AIndex] as TTypeDef;
  525. end;
  526. function TTypeDefs.GetEnumerator: TTypeDefEnumerator;
  527. begin
  528. Result:=TTypeDefEnumerator.Create(Self);
  529. end;
  530. function TTypeDefs.IndexOf(ATypename: String): Integer;
  531. begin
  532. Result:=Count-1;
  533. While (Result>=0) and (CompareText(ATypeName,GetD(Result).PascalName)<>0) do
  534. Dec(Result);
  535. end;
  536. function TTypeDefs.Find(ATypename: String): TTypeDef;
  537. Var
  538. I : Integer;
  539. begin
  540. I:=IndexOf(ATypeName);
  541. if (I=-1) then
  542. Result:=Nil
  543. else
  544. Result:=GetD(I);
  545. end;
  546. function TTypeDefs.AddTypeDef(ADataType: TDataType; APascalName: String;
  547. ASchema: TSchema): TTypeDef;
  548. begin
  549. Result:=Add as TTypeDef;
  550. Result.DataType:=ADataType;
  551. Result.PascalName:=APascalName;
  552. Result.Schema:=ASchema;
  553. end;
  554. { TSchema }
  555. function TSchema.DoGetTypeName(PrependT : Boolean) : String;
  556. begin
  557. Result:=FTypeName;
  558. if (Result='') and Assigned(TypeDef) then
  559. Result:=TypeDef.PascalName;
  560. If Result='' then
  561. begin
  562. If BaseType then
  563. Result:=GetBaseTypeName
  564. else if (_type='array') and Assigned(Items) then
  565. begin
  566. Result:=Items.DoGetTypeName(False);
  567. if (Result<>'') and not Assigned(Items.TypeDef) then
  568. begin
  569. if PrependT and (items._type<>'object') and (items._type<>'array') then
  570. Result:='T'+Result;
  571. Result:=Result+'Array';
  572. end;
  573. end;
  574. end;
  575. end;
  576. function TSchema.GetTypeName: String;
  577. begin
  578. Result:=DoGetTypeName(True);
  579. end;
  580. Function TSchema.ClassProperties: TProperties;
  581. begin
  582. If Length(FProperties)>0 then
  583. Result:=FProperties
  584. //else if Assigned(Items) then
  585. // Result:=Items.properties
  586. else
  587. Result:=Nil
  588. end;
  589. { TGoogleRestDescription }
  590. { TDiscoveryJSONToPas }
  591. Constructor TDiscoveryJSONToPas.Create(AOwner: TComponent);
  592. begin
  593. inherited Create(AOwner);
  594. FDescription:=TGoogleRestDescription.Create;
  595. BaseClassName:='TGoogleBaseObject';
  596. BaseListClassName:='TGoogleBaseObjectList';
  597. FResourceSuffix:='Resource';
  598. ArrayItemSuffix:='Item';
  599. PropertyTypeSuffix:='Type';
  600. // UseListForArray:=True;
  601. end;
  602. Destructor TDiscoveryJSONToPas.Destroy;
  603. begin
  604. FreeAndNil(FDescription);
  605. inherited Destroy;
  606. end;
  607. Procedure TDiscoveryJSONToPas.LoadFromStream(Const AStream: TStream);
  608. Var
  609. D : TJSONData;
  610. begin
  611. D:=GetJSON(AStream,True);
  612. try
  613. if Not (D is TJSONObject) then
  614. Raise EGoogleAPI.Create('Source does not contain a valid JSON object');
  615. LoadFromJSON(D as TJSONObject)
  616. finally
  617. D.Free;
  618. end;
  619. end;
  620. Procedure TDiscoveryJSONToPas.LoadFromJSON(Const JSON: TJSONObject);
  621. begin
  622. Description.LoadFromJSON(JSON);
  623. end;
  624. function TDiscoveryJSONToPas.GetSchemaDataType(S: TSchema): TDataType;
  625. begin
  626. if (S._type='array') then
  627. Result:=dtArray
  628. else if S._type='object' then
  629. Result:=dtClass
  630. else
  631. Result:=dtAlias;
  632. end;
  633. function TDiscoveryJSONToPas.GetUseListForArray: Boolean;
  634. begin
  635. Result:=gcoUseListForArray in CodeOPtions;
  636. end;
  637. Function TDiscoveryJSONToPas.AddType(ASchema: TSchema; NamePrefix: String;
  638. IsTopLevel: Boolean): TTypeDef;
  639. Function DoAdd(DT : TDataType; TCN : String; S,ITS : TSchema) : TTypeDef;
  640. Var
  641. Msg : String;
  642. begin
  643. Result:=Nil;
  644. if (FTypes.IndexOf(TCN)<>-1) then
  645. Raise Exception.CreateFmt('Type already exists : "%s"',[TCN]);
  646. Result:=FTypes.AddTypeDef(dt,TCN,S);
  647. Result.ItemSchema:=ITS;
  648. Result.Toplevel:=isTopLevel;
  649. Str(dt,Msg);
  650. Msg:=Format('[%s] : Adding %s (%s) from ',[NamePrefix,TCN,Msg]);
  651. if Assigned(S) then
  652. Msg:=Msg+S.DebugName;
  653. if Assigned(ItS) then
  654. Msg:=Msg+Format(' (Array item: %s)',[its.DebugName]);
  655. DoLog(Msg);
  656. end;
  657. Var
  658. CN,TCN : String;
  659. Dt : TDataType;
  660. begin
  661. dt:=GetSchemaDataType(ASchema);
  662. CN:=NamePrefix+ASchema.Name;
  663. if (dt=dtArray) and (NamePrefix<>'') then
  664. CN:=CN+'Array';
  665. TCN:='T'+CN;
  666. Result:=doAdd(dt,TCN,ASchema,Aschema.Items);
  667. Aschema.TypeDef:=Result;
  668. if (dt=dtClass) and isToplevel then
  669. doAdd(dtArray,TCN+'Array',Nil,Aschema);
  670. end;
  671. procedure TDiscoveryJSONToPas.CollectType(S: TSchema; NamePrefix: String; IsTopLevel : Boolean);
  672. Var
  673. AE : String;
  674. Dt : TDataType;
  675. BaseArrayElement : Boolean;
  676. begin
  677. if (S.Name='Component') and (NamePrefix='') then
  678. NamePrefix:='_';
  679. dt:=GetSchemaDataType(S);
  680. BaseArrayElement:=(dt=dtArray) and S.Items.BaseType;
  681. DoLog('[%s] Examining : %s (Ref : %s type: %s) Toplevel %s',[NamePrefix,S.Name,S.ref,S._type,BoolToStr(IsTopLevel,'True','False')]);
  682. case dt of
  683. dtArray : if Not BaseArrayElement and (S.Items.Ref='') then
  684. begin
  685. AE:=S.Name;
  686. if S.Items.Name='' then
  687. AE:=AE+ArrayItemSuffix;
  688. DoLog('Array, adding array item type first (%s)',[AE]);
  689. CollectType(S.Items,NamePrefix+AE,isTopLevel);
  690. end;
  691. dtClass :
  692. if (S.Ref='') then
  693. begin
  694. DoLog('Class type, adding properties first');
  695. CollectTypes(S.Properties,NamePrefix+S.Name+PropertyTypeSuffix);
  696. end;
  697. end;
  698. if (NamePrefix='') then
  699. AddType(S,'',True)
  700. else if (Not S.BaseType) and (Not BaseArrayElement) and (S.Ref='') then
  701. AddType(S,NamePrefix,IsTopLevel);
  702. end;
  703. function TDiscoveryJSONToPas.GetFlat: Boolean;
  704. begin
  705. Result:=gcoFlatResources in CodeOPtions;
  706. end;
  707. Procedure TDiscoveryJSONToPas.CollectTypes(Schemas: TSchemas; NamePrefix: String
  708. );
  709. Var
  710. S : TSchema;
  711. begin
  712. For S in Schemas do
  713. CollectType(S,NamePrefix,NamePrefix='');
  714. end;
  715. Procedure TDiscoveryJSONToPas.ResolveRefs;
  716. Var
  717. Lookup : TStringList;
  718. Function DoFind (S : TSchema; C : String) : TSchema;
  719. Var
  720. idx : Integer;
  721. begin
  722. Idx:=Lookup.IndexOf(S.Ref);
  723. if idx<>-1 then
  724. Result:=TSchema(Lookup.Objects[idx])
  725. else
  726. Raise Exception.CreateFmt('Could not find reference %s (Context: %s)',[S.Name,C]);
  727. end;
  728. Procedure AddSchema(ASchema : TSchema);
  729. begin
  730. if Assigned(ASchema) then
  731. begin
  732. if (ASchema.Name<>'') then
  733. begin
  734. Lookup.AddObject(ASchema.Name,ASchema)
  735. end;
  736. end
  737. end;
  738. Procedure DoResolve(ASchema : TSchema);
  739. Var
  740. S2 : TSchema;
  741. begin
  742. if Assigned(ASchema) then
  743. begin
  744. if (ASchema.Ref<>'') and (ASchema.Refschema=Nil) then
  745. ASchema.Refschema:=DoFind(ASchema,ASchema.Name);
  746. if Assigned(ASchema.Items) then
  747. DoResolve(ASchema.Items);
  748. if Length(ASchema.Properties)<>0 then
  749. For S2 in ASchema.Properties do
  750. begin
  751. DoResolve(S2);
  752. DoResolve(S2.Items);
  753. end;
  754. end;
  755. end;
  756. Var
  757. T : TTypeDef;
  758. S : TSchema;
  759. begin
  760. Lookup:=TStringList.Create;
  761. try
  762. for S in Description.Schemas do
  763. AddSchema(S);
  764. Lookup.Sorted:=True;
  765. For T in FTypes do
  766. begin
  767. DoResolve(T.Schema);
  768. DoResolve(T.ItemSchema);
  769. end;
  770. finally
  771. Lookup.Free;
  772. end;
  773. end;
  774. Procedure TDiscoveryJSONToPas.CollectTypes;
  775. Var
  776. S : TTypeDef;
  777. Msg : String;
  778. begin
  779. CollectTypes(Description.Schemas,ClassPrefix);
  780. For S in FTypes do
  781. begin
  782. Str(S.DataType,Msg);
  783. DoLog('Created data type %s (%s)',[S.PascalName,Msg]);
  784. end;
  785. ResolveRefs;
  786. end;
  787. Function TDiscoveryJSONToPas.BaseUnits: String;
  788. begin
  789. Result:='googleservice, restbase, googlebase'
  790. end;
  791. Class function TSchema.BaseType(ATypeName: String): Boolean;
  792. begin
  793. Result:=(ATypeName='boolean') or (ATypeName='string') or (ATypeName='number') or (ATypeName='any') or (ATypeName='integer');
  794. end;
  795. Class function TSchema.GetBaseTypeName(AType, AFormat: String): string;
  796. begin
  797. Result:=AType;
  798. if Result='any' then
  799. Result:='TJSONSchema'
  800. else if Result='integer' then
  801. begin
  802. if (AFormat='int64') then
  803. Result:='int64'
  804. else
  805. Result:='integer'
  806. end
  807. else if Result='number' then
  808. begin
  809. if (AFormat='double') then
  810. Result:='double'
  811. else
  812. Result:='integer'
  813. end
  814. else if Result='string' then
  815. if Aformat='date-time' then
  816. Result:='TDatetime'
  817. else if Aformat='date' then
  818. Result:='TDate'
  819. else
  820. Result:='String';
  821. end;
  822. {$IFDEF VER2_6}
  823. Procedure TSchema.SetArrayLength(const AName: String; ALength: Longint);
  824. begin
  825. Case AName of
  826. 'enumdescriptions' : SetLength(FenumDescriptions,ALength);
  827. 'properties' : SetLength(FProperties,ALength);
  828. 'methods' : SetLength(FMethods,ALength);
  829. 'resources' : SetLength(FResources,ALength);
  830. else
  831. inherited SetArrayLength(AName, ALength);
  832. end;
  833. end;
  834. {$ENDIF}
  835. Function TSchema.DebugName: String;
  836. begin
  837. Result:=sysutils.Format('(Name: %s, Pascal Type : %s, type : %s, Ref: %s)',[Name,TypeName,_type,Ref]);
  838. end;
  839. function TSchema.GetBaseTypeName: string;
  840. begin
  841. Result:=GetBaseTypeName(_type,Format);
  842. end;
  843. Function TSchema.BaseType: Boolean;
  844. begin
  845. Result:=BaseType(_type)
  846. end;
  847. Function TDiscoveryJSONToPas.GetPropertyType(AClassName: String;
  848. ASchema: TSchema): String;
  849. begin
  850. DoLog('Checking property type "%s" property schema %s',[AClassName,ASchema.DebugName]);
  851. Result:=ASchema.TypeName;
  852. if (Result='') then
  853. begin
  854. Result:=ASchema.ref;
  855. if Result='' then
  856. begin
  857. Result:=ASchema._type;
  858. if TSchema.BaseType(Result) then
  859. Result:=ASchema.GetBaseTypeName;
  860. end
  861. else if Not Assigned(ASchema.Refschema) then
  862. Raise Exception.CreateFmt('%s : Unresolved property schema (%s) type reference : %s',[AClassName,ASchema.Name,ASchema.Ref])
  863. else
  864. Result:=ASchema.Refschema.TypeName;
  865. end;
  866. if Result='array' then
  867. begin
  868. if Aschema.Items.TypeDef<>Nil then
  869. Result:=Aschema.Items.TypeDef.PascalName
  870. else if (ASchema.Items.Ref<>'') then
  871. begin
  872. if not Assigned(ASchema.Items.Refschema) then
  873. Raise Exception.CreateFmt('%s : Unresolved property (%s) type reference : %s',[AClassName,ASchema.Name,ASchema.Ref]);
  874. Result:=Aschema.Items.RefSchema.TypeName+'Array';
  875. end
  876. else
  877. Result:=ASchema.Items.TypeName;
  878. end
  879. else if Result='object' then
  880. if (ASchema.ref<>'') then
  881. Result:='T'+ClassPrefix+ASchema.ref
  882. else
  883. Result:=AClassName+ASchema.Name;
  884. end;
  885. Procedure TDiscoveryJSONToPas.CreateClassDeclaration(AClassName: String;
  886. ASchema: TSchema);
  887. Var
  888. S : TSchema;
  889. N : String;
  890. NeedSetArrayLength, NeedGetWritename : Boolean;
  891. TN : String;
  892. Idx,PropertyIndex,PropertyOptions : Integer;
  893. L : TStringList;
  894. begin
  895. if ASchema=Nil then
  896. Raise Exception.Create(AClassName+' : no Schema');
  897. ClassHeader(AClassName);
  898. AddLn('%s = Class(%s)',[AClassName,BaseClassName]);
  899. AddLn('Private');
  900. NeedGetWriteName:=False;
  901. NeedSetArrayLength:=False;
  902. IncIndent;
  903. L:=TStringList.Create;
  904. try
  905. For S in ASchema.Properties do
  906. begin
  907. N:=TBaseObject.CleanPropertyName(S.Name);
  908. Repeat
  909. Idx:=L.IndexOf(N);
  910. if (idx=-1) then
  911. Idx:=L.IndexOf('F'+N);
  912. if (idx<>-1) then
  913. begin
  914. N:='_'+N;
  915. end;
  916. Until Idx=-1;
  917. NeedGetWritename:=NeedGetWritename or (CompareText(N,S.Name)<>0);
  918. NeedSetArrayLength:=NeedSetArrayLength or (S._type='array');
  919. S.PropertyName:=N;
  920. tn:=GetPropertyType(AClassName,S);
  921. AddLn('F%s : %s;',[N,tn]);
  922. L.Add(N);
  923. L.Add('F'+N);
  924. end;
  925. finally
  926. L.Free;
  927. end;
  928. DecIndent;
  929. AddLn('Protected');
  930. IncIndent;
  931. if NeedGetWriteName then
  932. AddLn('Class Function ExportPropertyName(Const AName : String) : string; override;');
  933. Comment('Property setters');
  934. For S in ASchema.ClassProperties do
  935. begin
  936. N:=S.PropertyName;
  937. tn:=GetPropertyType(AClassName,S);
  938. AddLn('Procedure Set%s(AIndex : Integer; const AValue : %s); virtual;',[N,tn]);
  939. end;
  940. if NeedSetArrayLength and not UseListForArray then
  941. begin
  942. Comment('2.6.4. bug workaround');
  943. Addln('{$IFDEF VER2_6}');
  944. Addln('Procedure SetArrayLength(Const AName : String; ALength : Longint); override;');
  945. Addln('{$ENDIF VER2_6}');
  946. end;
  947. DecIndent;
  948. AddLn('Public');
  949. IncIndent;
  950. if Assigned(ASchema.additionalProperties) then
  951. AddLn('Class Function AllowAdditionalProperties : Boolean; override;');
  952. DecIndent;
  953. AddLn('Published');
  954. IncIndent;
  955. PropertyIndex:=0;
  956. For S in ASchema.ClassProperties do
  957. begin
  958. N:=S.PropertyName;
  959. Tn:=GetPropertyType(AClassName,S);
  960. PropertyOptions:=0;
  961. Idx:=(PropertyIndex shl IndexShift) or PropertyOptions;
  962. AddLn('Property %s : %s Index %d Read F%s Write Set%s;',[N,TN,Idx, N,N]);
  963. Inc(PropertyIndex);
  964. end;
  965. DecIndent;
  966. AddLn('end;');
  967. AddLn('%sClass = Class of %s;',[AClassName,AClassName]);
  968. end;
  969. Procedure TDiscoveryJSONToPas.CreateArrayClassDeclaration(AClassName: String;
  970. ASchema, AItemSchema: TSchema);
  971. Var
  972. AEnumeratorName,AItemName : String;
  973. begin
  974. if AItemSchema=Nil then
  975. Raise Exception.Create(AClassName+' : no item Schema');
  976. AItemName:=GetPropertyType('',AItemSchema);
  977. AEnumeratorName:=AClassName+'Enumerator';
  978. ClassHeader(AEnumeratorName);
  979. AddLn('%s = Class(%s)',[AEnumeratorName,'TBaseListEnumerator']);
  980. AddLn('Public');
  981. IncIndent;
  982. AddLn('Function GetCurrent : %s; ',[AItemName]);
  983. AddLn('Property Current : %s Read GetCurrent;',[AItemName]);
  984. DecIndent;
  985. AddLn('end;');
  986. AddLn('');
  987. AddLn('');
  988. ClassHeader(AClassName);
  989. AddLn('%s = Class(%s)',[AClassName,BaseListClassName]);
  990. AddLn('Private');
  991. IncINdent;
  992. Addln('Function GetI (AIndex : Integer) : %s;',[AItemName]);
  993. Addln('Procedure SetI (AIndex : Integer; Const AValue: %s);',[AItemName]);
  994. DecIndent;
  995. AddLn('Protected');
  996. IncIndent;
  997. AddLn('Class Function ObjectClass : TBaseObjectClass; override;');
  998. DecIndent;
  999. AddLn('Public');
  1000. IncIndent;
  1001. AddLn('Function GetEnumerator : %s;',[AEnumeratorName]);
  1002. AddLn('Property Items[AIndex : Integer] : %s Read GetI Write SetI; default;',[AItemName]);
  1003. DecIndent;
  1004. AddLn('end;');
  1005. AddLn('%sClass = Class of %s;',[AClassName,AClassName]);
  1006. end;
  1007. procedure TDiscoveryJSONToPas.CreateSetArrayLength(AClassName: String; ASchema, AItemSchema: TSchema);
  1008. Var
  1009. S : TSchema;
  1010. N : String;
  1011. begin
  1012. Comment('2.6.4. bug workaround');
  1013. Addln('{$IFDEF VER2_6}');
  1014. Addln('Procedure %s.SetArrayLength(Const AName : String; ALength : Longint); ',[AClassName]);
  1015. Addln('');
  1016. AddLn('begin');
  1017. IncIndent;
  1018. AddLn('Case AName of');
  1019. For S in ASchema.ClassProperties do
  1020. if (S._type='array') then
  1021. begin
  1022. N:=S.PropertyName;
  1023. AddLn('''%s'' : SetLength(F%s,ALength);',[Lowercase(N),N]);
  1024. end;
  1025. AddLn('else');
  1026. IncIndent;
  1027. AddLn('Inherited SetArrayLength(AName,ALength);');
  1028. DecIndent;
  1029. AddLn('end;');
  1030. DecIndent;
  1031. AddLn('end;');
  1032. Addln('{$ENDIF VER2_6}');
  1033. Addln('');
  1034. end;
  1035. procedure TDiscoveryJSONToPas.CreateExportPropertyName(AClassName: String; ASchema, AItemSchema: TSchema);
  1036. Var
  1037. S : TSchema;
  1038. N : String;
  1039. begin
  1040. begin
  1041. Addln('');
  1042. AddLn('Class Function %s.ExportPropertyName(Const AName : String) :String;',[AClassName]);
  1043. Addln('');
  1044. AddLn('begin');
  1045. IncIndent;
  1046. AddLn('Case AName of');
  1047. For S in ASchema.ClassProperties do
  1048. begin
  1049. N:=S.PropertyName;
  1050. if (CompareText(N,S.Name)<>0) then
  1051. AddLn('''%s'' : Result:=''%s'';',[N,S.Name]);
  1052. end;
  1053. AddLn('else');
  1054. IncIndent;
  1055. AddLn('Result:=Inherited ExportPropertyName(AName);');
  1056. DecIndent;
  1057. AddLn('end;');
  1058. DecIndent;
  1059. AddLn('end;');
  1060. Addln('');
  1061. end;
  1062. end;
  1063. Procedure TDiscoveryJSONToPas.CreateClassImplementation(AClassName: String;
  1064. ASchema, AItemSchema: TSchema);
  1065. Var
  1066. S : TSchema;
  1067. N : String;
  1068. NeedSetArrayLength,NeedGetWritename : Boolean;
  1069. TN : String;
  1070. begin
  1071. NeedGetWriteName:=False;
  1072. NeedSetArrayLength:=False;
  1073. ClassHeader(AClassName);
  1074. For S in ASchema.ClassProperties do
  1075. begin
  1076. N:=S.PropertyName;
  1077. NeedSetArrayLength:=NeedSetArrayLength or (S._type='array');
  1078. NeedGetWritename:=NeedGetWritename or (CompareText(N,S.Name)<>0);
  1079. TN:=GetPropertyType(AClassName,S);
  1080. Addln('');
  1081. AddLn('Procedure %s.Set%s(AIndex : Integer; const AValue : %s); ',[AClassName,N,tn]);
  1082. SimpleMethodBody([Format('If (F%s=AValue) then exit;',[N]),
  1083. Format('F%s:=AValue;',[N]),
  1084. 'MarkPropertyChanged(AIndex);']);
  1085. Addln('');
  1086. end;
  1087. if NeedGetWriteName then
  1088. CreateExportPropertyName(AClassName,ASchema, AItemSchema);
  1089. if NeedSetArrayLength and not UseListForArray then
  1090. CreateSetArrayLength(AClassName,ASchema, AItemSchema);
  1091. Addln('');
  1092. if Assigned(ASchema.additionalProperties) then
  1093. begin
  1094. AddLn('Class Function %s.AllowAdditionalProperties : Boolean;',[AClassName]);
  1095. SimpleMethodBody(['Result:=True;']);
  1096. end;
  1097. Addln('');
  1098. end;
  1099. Procedure TDiscoveryJSONToPas.CreateArrayClassImplementation(
  1100. AClassName: String; ASchema, AItemSchema: TSchema);
  1101. Var
  1102. AEnumeratorName,AItemName : String;
  1103. begin
  1104. if AItemSchema=Nil then
  1105. Raise Exception.Create(AClassName+' : no Schema');
  1106. CreateArrayClassEnumeratorImplementation(ACLassName,ASchema,AItemSchema);
  1107. AItemName:=GetPropertyType('',AItemSchema);
  1108. AEnumeratorName:=AClassName+'Enumerator';
  1109. ClassHeader(AClassName);
  1110. Addln('');
  1111. Addln('Function %s.GetI (AIndex : Integer) : %s;',[AClassName,AItemName]);
  1112. SimpleMethodBody([Format('Result:=%s(Objects[AIndex]);',[AItemName])]);
  1113. Addln('');
  1114. Addln('Procedure %s.SetI (AIndex : Integer; Const AValue: %s);',[AClassName,AItemName]);
  1115. SimpleMethodBody(['Objects[AIndex]:=AValue;']);
  1116. Addln('');
  1117. AddLn('Class Function %s.ObjectClass : TBaseObjectClass;',[ACLassName]);
  1118. SimpleMethodBody([Format('Result:=%s;',[AItemName])]);
  1119. Addln('');
  1120. AddLn('Function %S.GetEnumerator : %s;',[ACLassName,AEnumeratorName]);
  1121. SimpleMethodBody([Format('Result:=%s(DoCreateEnumerator(%s));',[AEnumeratorName,AEnumeratorName])]);
  1122. Addln('');
  1123. end;
  1124. Procedure TDiscoveryJSONToPas.CreateArrayClassEnumeratorImplementation(
  1125. AClassName: String; ASchema, AItemSchema: TSchema);
  1126. Var
  1127. AEnumeratorName,AItemName : String;
  1128. begin
  1129. if AItemSchema=Nil then
  1130. Raise Exception.Create(AClassName+' : no ItemSchema');
  1131. AItemName:=GetPropertyType('',AItemSchema);
  1132. AEnumeratorName:=AClassName+'Enumerator';
  1133. ClassHeader(AEnumeratorName);
  1134. AddLn('Function %s.GetCurrent : %s;',[AEnumeratorName,AItemName]);
  1135. SimpleMethodBody([Format('Result:=%s(Inherited GetCurrent);',[AItemName])]);
  1136. end;
  1137. Function TDiscoveryJSONToPas.GetAPIClassName: String;
  1138. begin
  1139. Result:=Format('T%s%sAPI',[ClassPrefix,PrettyPrint(Description.Name)])
  1140. end;
  1141. Procedure TDiscoveryJSONToPas.CreateInterface;
  1142. procedure AddTypeDecl(S : TTypeDef);
  1143. begin
  1144. Case S.DataType of
  1145. dtAlias : AddLn('%s = %s;',[S.PascalName,S.Schema.GetBaseTypeName]);
  1146. dtArray :
  1147. if UseListForArray then
  1148. AddLn('%s = Class;',[S.PascalName])
  1149. else
  1150. AddLn('%s = Array of %s;',[S.PascalName,GetPropertyType('',S.ItemSchema)]);
  1151. dtClass : AddLn('%s = Class;',[S.PascalName]);
  1152. end;
  1153. end;
  1154. Procedure DoTypeLoops(DoTopLevel : Boolean);
  1155. Var
  1156. S : TTypeDef;
  1157. begin
  1158. For S in FTypes do
  1159. if (S.DataType=dtAlias) and (S.TopLevel=DoTopLevel) then
  1160. AddTypeDecl(S);
  1161. For S in FTypes do
  1162. if (S.DataType=dtClass) and (S.TopLevel=DoTopLevel) then
  1163. AddTypeDecl(S);
  1164. For S in FTypes do
  1165. if (S.DataType=dtArray) and (S.TopLevel=DoTopLevel) then
  1166. AddTypeDecl(S);
  1167. end;
  1168. Var
  1169. S : TTypeDef;
  1170. begin
  1171. Addln('type');
  1172. IncIndent;
  1173. AddLn('');
  1174. Comment('Top-level schema types');
  1175. DoTypeLoops(True);
  1176. Comment('Anonymous types, using auto-generated names');
  1177. DoTypeLoops(False);
  1178. For S in FTypes do
  1179. if S.DataType=dtClass then
  1180. CreateClassDeclaration(S.PascalName,S.Schema)
  1181. else if (S.DataType=dtArray) and UseListForArray then
  1182. CreateArrayClassDeclaration(S.PascalName,S.Schema,S.ItemSchema);
  1183. CreateResourceDeclarations('',Description.Resources);
  1184. CreateAPIClassDeclaration;
  1185. DecIndent;
  1186. end;
  1187. procedure TDiscoveryJSONToPas.CreateResourceDeclarations(Const APrefix : String; Resources : TSchemas);
  1188. var
  1189. R : TSchema;
  1190. begin
  1191. For R in Resources do
  1192. begin
  1193. if Assigned(R.resources) then
  1194. if FlatResources then
  1195. CreateResourceDeclarations(APrefix,R.Resources)
  1196. else
  1197. CreateResourceDeclarations(APrefix+PrettyPrint(R.Name),R.Resources);
  1198. R.TypeName:=GetResourceClassName(APrefix,R);
  1199. CreateResourceClassDeclaration(APrefix,R);
  1200. end;
  1201. end;
  1202. Procedure TDiscoveryJSONToPas.CreateImplementation;
  1203. Var
  1204. S : TTypeDef;
  1205. begin
  1206. For S in FTypes do
  1207. Case S.DataType of
  1208. dtClass: CreateClassImplementation(S.PascalName,S.Schema,S.ItemSchema);
  1209. dtArray: if UseListForArray then
  1210. CreateArrayClassImplementation(S.PascalName,S.Schema,S.ItemSchema);
  1211. end;
  1212. CreateResourceClassImplementations('',Description.Resources);
  1213. CreateAPIClassImplementation;
  1214. end;
  1215. Procedure TDiscoveryJSONToPas.CreateResourceClassImplementations(Const APrefix : String; Resources : TSchemas);
  1216. var
  1217. R : TSchema;
  1218. begin
  1219. For R in Resources do
  1220. begin
  1221. if Assigned(R.Resources) then
  1222. CreateResourceClassImplementations(ConstructResourcePrefix(APrefix,R),R.Resources);
  1223. CreateResourceClassImplementation(APrefix,R);
  1224. end;
  1225. end;
  1226. Function TDiscoveryJSONToPas.GetResourceMethodSignature(M: TRestmethod; Out
  1227. IsFunction: Boolean; QueryOptionType: String; AddTypes: Boolean): String;
  1228. Const
  1229. Seps : Array[Boolean] of String = (',','; ');
  1230. Procedure AddSep(Var S : String);
  1231. begin
  1232. if (S<>'') then
  1233. S:=S+Seps[AddTypes];
  1234. end;
  1235. Var
  1236. P : TRestMethodParam;
  1237. S : String;
  1238. Q : Boolean; // Was AQuery encountered in options
  1239. begin
  1240. Q:=False;
  1241. S:='';
  1242. For P in M.parameters do
  1243. if (P.Location='path') and P.Required then
  1244. begin
  1245. Q:=Q or (CompareText(p.SourceName,'aquery')=0);
  1246. AddSep(S);
  1247. S:=S+P.SourceName;
  1248. If AddTypes then
  1249. S:=S+': '+P._type;
  1250. end;
  1251. For P in M.parameters do
  1252. if (P.Location='path') and not P.Required then
  1253. begin
  1254. Q:=Q or (CompareText(p.SourceName,'aquery')=0);
  1255. AddSep(S);
  1256. S:=S+P.SourceName;
  1257. if AddTypes then
  1258. begin
  1259. S:=S+': '+P._type + ' = ';
  1260. Case p._type of
  1261. 'string' : S:=S+'''''';
  1262. 'number' : S:=S+'0';
  1263. 'object' : S:=S+'nil';
  1264. end;
  1265. end;
  1266. end;
  1267. if M.Request<>Nil then
  1268. begin
  1269. AddSep(S);
  1270. S:=S+'a'+M.request.ref;
  1271. If AddTypes then
  1272. S:=S+' : T'+ClassPrefix+M.request.ref;
  1273. end;
  1274. if (QueryOptionType<>'') then
  1275. begin
  1276. AddSep(S);
  1277. if AddTypes then
  1278. S:=S+'AQuery : '+QueryOptionType
  1279. else
  1280. S:=S+QueryOptionType; // Will be name instead of type;
  1281. end;
  1282. if (S<>'') then
  1283. S:='('+S+')';
  1284. S:=PrettyPrint(TBaseObject.CleanPropertyName(M.Name))+S;
  1285. isFunction:=M.Response<>Nil;
  1286. if isFunction and AddTypes then
  1287. S:=S+' : T'+ClassPrefix+M.response.ref;
  1288. Result:=S;
  1289. end;
  1290. Function TDiscoveryJSONToPas.DescribeMethodParams(M: TRestMethod
  1291. ): TParamLocations;
  1292. Var
  1293. P : TRestMethodParam;
  1294. begin
  1295. Result:=[];
  1296. For P in M.Parameters do
  1297. Case P.location of
  1298. 'path' : Include(Result,plPath);
  1299. 'query' : Include(Result,plQuery);
  1300. end;
  1301. end;
  1302. Function TDiscoveryJSONToPas.HavePathParams(M: TRestMethod): Boolean;
  1303. begin
  1304. Result:=plPath in DescribeMethodParams(M);
  1305. end;
  1306. Procedure TDiscoveryJSONToPas.CreateResourceMethodQueryParams(APrefix : String; Res: TSchema;
  1307. M: TRestMethod);
  1308. Var
  1309. P : TRestMethodParam;
  1310. RN,RCN,MN : String;
  1311. begin
  1312. RN:=APrefix+PrettyPrint(Res.Name);
  1313. RCN:=Res.TypeName;
  1314. MN:=PrettyPrint(M.Name);
  1315. Addln('');
  1316. Comment(Format('Optional query Options for %s, method %s',[RCN,MN]));
  1317. Addln('');
  1318. Addln('T%s%sOptions = Record',[RN,MN]);
  1319. IncIndent;
  1320. For P in M.parameters do
  1321. begin
  1322. if (P.location='query') then
  1323. if p.format='int64' then
  1324. AddLn('%s : int64;',[P.Sourcename])
  1325. else
  1326. AddLn('%s : %s;',[P.sourcename,P.GetBaseTypeName]);
  1327. end;
  1328. DecIndent;
  1329. Addln('end;');
  1330. Addln('');
  1331. end;
  1332. Function TDiscoveryJSONToPas.HaveQueryParams(M: TRestMethod): Boolean;
  1333. begin
  1334. Result:=plQuery in DescribeMethodParams(M);
  1335. end;
  1336. Function TDiscoveryJSONToPas.GetResourceClassName(Const APrefix: String;
  1337. Res: TSchema): String;
  1338. Var
  1339. Suffix : String;
  1340. begin
  1341. if (Res.TypeName<>'') and (Res.TypeName<>Res.Name) then
  1342. Result:=Res.TypeName
  1343. else
  1344. begin
  1345. Suffix:='Resource';
  1346. Repeat
  1347. Result:=Format('T%s%s%s%s',[ClassPrefix,APrefix,PrettyPrint(Res.Name),Suffix]);
  1348. Suffix:='_'+Suffix;
  1349. Until FTypes.IndexOf(Result)=-1;
  1350. end
  1351. end;
  1352. procedure TDiscoveryJSONToPas.AssignParamNames(Res: TSchema; M: TRestMethod);
  1353. // Google API has case sensitive names. We need to make sure the names are unique in a case insensitive manner.
  1354. // This is done by assigning the 'source name'
  1355. Var
  1356. T : TStringList;
  1357. P : TRestMethodParam;
  1358. N : String;
  1359. begin
  1360. T:=TStringList.Create;
  1361. try
  1362. // The request also has a parameter name
  1363. If Assigned(M.request) then
  1364. T.Add('a'+M.request.ref);
  1365. // Some identifiers that are 'reserved' by the base classes.
  1366. With T do
  1367. begin
  1368. Add('Name');
  1369. Add('ResourceName');
  1370. Add('DefaultAPI');
  1371. Add('API');
  1372. Add('Notification');
  1373. Add('UpdateAction');
  1374. Add('ExecuteAction');
  1375. end;
  1376. // Actual paramters
  1377. For P in M.parameters do
  1378. begin
  1379. N:=P.Name;
  1380. While T.IndexOf(N)<>-1 do
  1381. begin
  1382. N:='_'+N;
  1383. end;
  1384. T.Add(N);
  1385. P.SourceName:=TbaseObject.CleanPropertyName(N);
  1386. end;
  1387. finally
  1388. T.Free;
  1389. end;
  1390. end;
  1391. function TDiscoveryJSONToPas.ReservedMethod(ANAme: String): boolean;
  1392. begin
  1393. AName:=';'+lowerCase(AName)+';';
  1394. Result:=Pos(AName,';create;destroy;free;')<>0;
  1395. end;
  1396. Procedure TDiscoveryJSONToPas.CreateResourceClassDeclaration(
  1397. Const APrefix: String; Res: TSchema);
  1398. Var
  1399. M : TRestMethod;
  1400. CN,S : String;
  1401. HaveOpt : Boolean;
  1402. IsFunc : Boolean;
  1403. begin
  1404. CN:=Res.TypeName;
  1405. ClassHeader(CN);
  1406. For M in Res.methods do
  1407. begin
  1408. AssignParamNames(Res,M);
  1409. if HaveQueryParams(M) then
  1410. begin
  1411. CreateResourceMethodQueryParams(APrefix,Res,M);
  1412. end;
  1413. end;
  1414. Addln('%s = Class(TGoogleResource)',[CN]);
  1415. if Assigned(Res.Resources) then
  1416. begin
  1417. Addln('Private');
  1418. IncIndent;
  1419. CreateResourceInstanceFields('',Res.Resources);
  1420. CreateResourceInstanceGetters('',Res.Resources);
  1421. DecIndent;
  1422. end;
  1423. Addln('Public');
  1424. IncIndent;
  1425. AddLn('Class Function ResourceName : String; override;');
  1426. AddLn('Class Function DefaultAPI : TGoogleAPIClass; override;');
  1427. For M in Res.methods do
  1428. begin
  1429. HaveOpt:=HaveQueryParams(M);
  1430. if HaveOpt then
  1431. S:=GetResourceMethodSignature(M,IsFunc,'string = ''''')
  1432. else
  1433. S:=GetResourceMethodSignature(M,IsFunc,'');
  1434. if IsFunc then
  1435. S:='Function '+S
  1436. else
  1437. S:='Procedure '+S;
  1438. if ReservedMethod(M.Name) then
  1439. S:=S+';overload';
  1440. AddLn(S+';');
  1441. if HaveOpt then
  1442. begin
  1443. S:=GetResourceMethodSignature(M,IsFunc,Format('T%s%sOptions',[APrefix+PrettyPrint(Res.Name),M.Name]));
  1444. if IsFunc then
  1445. S:='Function '+S
  1446. else
  1447. S:='Procedure '+S;
  1448. if ReservedMethod(M.Name) then
  1449. S:=S+';overload';
  1450. AddLn(S+';');
  1451. end;
  1452. end;
  1453. if Assigned(Res.Resources) then
  1454. begin
  1455. CreateResourceAPI('',Res.resources);
  1456. CreateResourceProperties('',Res.resources);
  1457. end;
  1458. DecIndent;
  1459. Addln('end;',[Res.name]);
  1460. AddLn('');
  1461. end;
  1462. Procedure TDiscoveryJSONToPas.CreateResourceClassMethodsImplementation(
  1463. Res: TSchema; Const AClassName: String);
  1464. begin
  1465. AddLn('');
  1466. Addln('Class Function %s.ResourceName : String;',[AClassName]);
  1467. AddLn('');
  1468. AddLn('begin');
  1469. IncIndent;
  1470. AddLn('Result:=''%s'';',[Res.name]);
  1471. DecIndent;
  1472. AddLn('end;');
  1473. AddLn('');
  1474. Addln('Class Function %s.DefaultAPI : TGoogleAPIClass;',[AClassName]);
  1475. AddLn('');
  1476. AddLn('begin');
  1477. IncIndent;
  1478. AddLn('Result:=T%s%sAPI;',[ClassPrefix,Description.Name]);
  1479. DecIndent;
  1480. AddLn('end;');
  1481. AddLn('');
  1482. end;
  1483. Procedure TDiscoveryJSONToPas.CreateResourceMethodImplementationOptions(Const APrefix,AClassName: String; Res: TSchema; M: TRestMethod);
  1484. Var
  1485. P : TRestMethodParam;
  1486. S: String;
  1487. IsFunc : Boolean;
  1488. begin
  1489. S:=GetResourceMethodSignature(M,IsFunc,Format('T%s%sOptions',[APrefix+PrettyPrint(Res.Name),M.Name]));
  1490. S:=AClassName+'.'+S;
  1491. if IsFunc then
  1492. S:='Function '+S
  1493. else
  1494. S:='Procedure '+S;
  1495. Addln('');
  1496. AddLn(S+';');
  1497. Addln('');
  1498. AddLn('Var');
  1499. IncIndent;
  1500. Addln('_Q : String;');
  1501. DecIndent;
  1502. Addln('');
  1503. AddLn('begin');
  1504. IncIndent;
  1505. AddLn('_Q:='''';');
  1506. For P in M.parameters do
  1507. begin
  1508. if (P.location='query') then
  1509. AddLn('AddToQuery(_Q,''%s'',AQuery.%s);',[P.name,P.SourceName]);
  1510. end;
  1511. S:=GetResourceMethodSignature(M,IsFunc,'_Q',False);
  1512. if IsFunc then
  1513. S:='Result:='+S;
  1514. AddLn(S+';');
  1515. DecIndent;
  1516. AddLn('end;');
  1517. Addln('');
  1518. end;
  1519. Procedure TDiscoveryJSONToPas.CreateResourceMethodImplementation(
  1520. AClassName: String; Res: TSchema; M: TRestMethod);
  1521. Var
  1522. P : TRestMethodParam;
  1523. Q,RC,O,S,PA : String;
  1524. IsFunc : Boolean;
  1525. PL: TParamLocations;
  1526. begin
  1527. PL:=DescribeMethodParams(M);
  1528. if plQuery in PL then
  1529. S:=GetResourceMethodSignature(M,IsFunc,'string = ''''')
  1530. else
  1531. S:=GetResourceMethodSignature(M,IsFunc,'');
  1532. S:=AClassName+'.'+S;
  1533. if IsFunc then
  1534. S:='Function '+S
  1535. else
  1536. S:='Procedure '+S;
  1537. AddLn(S+';');
  1538. AddLn('');
  1539. AddLn('Const');
  1540. IncIndent;
  1541. AddLn('_HTTPMethod = ''%s'';',[M.httpMethod]);
  1542. AddLn('_Path = ''%s'';',[M.path]);
  1543. AddLn('_Methodid = ''%s'';',[M.id]);
  1544. DecIndent;
  1545. AddLn('');
  1546. if (plPath in PL) then
  1547. begin
  1548. AddLn('Var');
  1549. IncIndent;
  1550. Addln('_P : String;');
  1551. DecIndent;
  1552. Addln('');
  1553. end;
  1554. Addln('begin');
  1555. IncIndent;
  1556. S:='';
  1557. PA:='_Path';
  1558. if (plPath in PL) then
  1559. begin
  1560. for P in M.parameters do
  1561. if P.location='path' then
  1562. begin
  1563. if (S<>'') then
  1564. S:=S+',';
  1565. S:=S+Format('''%s'',%s',[p.name,p.sourcename]);
  1566. end;
  1567. AddLn('_P:=SubstitutePath(_Path,[%s]);',[S]);
  1568. PA:='_P';
  1569. end;
  1570. if M.request<>Nil then
  1571. O:='a'+M.request.ref
  1572. else
  1573. O:='Nil';
  1574. if (M.response<>Nil) then
  1575. RC:='T'+ClassPrefix+M.response.ref
  1576. else
  1577. RC:='Nil';
  1578. if (plQuery in PL) then
  1579. Q:='AQuery'
  1580. else
  1581. Q:='''''';
  1582. S:=Format('ServiceCall(_HTTPMethod,%s,%s,%s,%s)',[PA,Q,O,RC]);
  1583. if isFunc then
  1584. S:='Result:='+S+' as T'+ClassPrefix+M.response.ref;
  1585. AddLn(S+';');
  1586. DecIndent;
  1587. Addln('end;');
  1588. Addln('');
  1589. end;
  1590. Procedure TDiscoveryJSONToPas.CreateResourceClassImplementation(Const APrefix : String; Res: TSchema);
  1591. Var
  1592. CN : String;
  1593. M : TRestMethod;
  1594. PL: TParamLocations;
  1595. begin
  1596. CN:=Res.TypeName;
  1597. ClassHeader(CN);
  1598. CreateResourceClassMethodsImplementation(Res,CN);
  1599. For M in Res.methods do
  1600. begin
  1601. PL:=DescribeMethodParams(M);
  1602. CreateResourceMethodImplementation(CN,Res,M);
  1603. if plQuery in PL then
  1604. CreateResourceMethodImplementationOptions(APrefix,CN,Res,M);
  1605. end;
  1606. AddLn('');
  1607. if Assigned(Res.resources) then
  1608. CreateResourceAPIFunctionImplementations(CN,'',Res.resources);
  1609. end;
  1610. Procedure TDiscoveryJSONToPas.CreateResourceInstanceFields(Const APrefix : String;Resources : TSchemas);
  1611. Var
  1612. R : TSchema;
  1613. begin
  1614. For R in Resources do
  1615. begin
  1616. If Assigned(R.Resources) then
  1617. CreateResourceInstanceFields(ConstructResourcePrefix(APrefix,R),R.Resources);
  1618. AddLn('F%sInstance : %s;',[APrefix+PrettyPrint(R.Name),R.TypeName]);
  1619. end;
  1620. end;
  1621. Function TDiscoveryJSONToPas.ConstructResourcePrefix(Const APrefix : String; AResource : TSchema) : String;
  1622. begin
  1623. if FlatResources then
  1624. Result:=APrefix
  1625. else
  1626. Result:=APrefix+PrettyPrint(AResource.Name);
  1627. end;
  1628. Procedure TDiscoveryJSONToPas.CreateResourceInstanceGetters(Const APrefix : String; Resources : TSchemas);
  1629. Var
  1630. R : TSchema;
  1631. begin
  1632. For R in Resources do
  1633. begin
  1634. If Assigned(R.Resources) then
  1635. CreateResourceInstanceGetters(ConstructResourcePrefix(APrefix,R),R.Resources);
  1636. AddLn('Function Get%sInstance : %s;virtual;',[APrefix+PrettyPrint(R.Name),R.TypeName]);
  1637. end;
  1638. end;
  1639. Procedure TDiscoveryJSONToPas.CreateResourceProperties(Const APrefix : String; Resources : TSchemas);
  1640. Var
  1641. R : TSchema;
  1642. begin
  1643. For R in Resources do
  1644. begin
  1645. If Assigned(R.Resources) then
  1646. CreateResourceProperties(ConstructResourcePrefix(APrefix,R),R.Resources);
  1647. AddLn('Property %sResource : %s Read Get%sInstance;',[APrefix+PrettyPrint(R.Name),R.TypeName,APrefix+PrettyPrint(R.Name)]);
  1648. end;
  1649. end;
  1650. Procedure TDiscoveryJSONToPas.CreateResourceAPI(Const APrefix : String; Resources : TSchemas);
  1651. Var
  1652. R : TSchema;
  1653. begin
  1654. For R in Resources do
  1655. begin
  1656. If Assigned(R.Resources) then
  1657. CreateResourceAPI(ConstructResourcePrefix(APrefix,R),R.Resources);
  1658. AddLn('Function Create%sResource(AOwner : TComponent) : %s;virtual;overload;',[APrefix+PrettyPrint(R.Name),R.TypeName]);
  1659. AddLn('Function Create%sResource : %s;virtual;overload;',[APrefix+PrettyPrint(R.Name),R.TypeName]);
  1660. end;
  1661. end;
  1662. Procedure TDiscoveryJSONToPas.CreateAPIClassDeclaration;
  1663. Var
  1664. CN : String;
  1665. begin
  1666. CN:=GetAPIClassName;
  1667. Classheader(CN);
  1668. AddLn('%s = Class(TGoogleAPI)',[CN]);
  1669. AddLn('Private');
  1670. IncIndent;
  1671. CreateResourceInstanceFields('',Description.resources);
  1672. CreateResourceInstanceGetters('',Description.resources);
  1673. DecINdent;
  1674. AddLn('Public');
  1675. IncIndent;
  1676. Comment('Override class functions with API info');
  1677. AddLn('Class Function APIName : String; override;');
  1678. AddLn('Class Function APIVersion : String; override;');
  1679. AddLn('Class Function APIRevision : String; override;');
  1680. AddLn('Class Function APIID : String; override;');
  1681. AddLn('Class Function APITitle : String; override;');
  1682. AddLn('Class Function APIDescription : String; override;');
  1683. AddLn('Class Function APIOwnerDomain : String; override;');
  1684. AddLn('Class Function APIOwnerName : String; override;');
  1685. AddLn('Class Function APIIcon16 : String; override;');
  1686. AddLn('Class Function APIIcon32 : String; override;');
  1687. AddLn('Class Function APIdocumentationLink : String; override;');
  1688. AddLn('Class Function APIrootUrl : string; override;');
  1689. AddLn('Class Function APIbasePath : string;override;');
  1690. AddLn('Class Function APIbaseURL : String;override;');
  1691. AddLn('Class Function APIProtocol : string;override;');
  1692. AddLn('Class Function APIservicePath : string;override;');
  1693. AddLn('Class Function APIbatchPath : String;override;');
  1694. AddLn('Class Function APIAuthScopes : TScopeInfoArray;override;');
  1695. AddLn('Class Function APINeedsAuth : Boolean;override;');
  1696. AddLn('Class Procedure RegisterAPIResources; override;');
  1697. Comment('Add create function for resources');
  1698. CreateResourceAPI('',Description.resources);
  1699. Comment('Add default on-demand instances for resources');
  1700. CreateResourceProperties('',Description.resources);
  1701. DecIndent;
  1702. AddLn('end;');
  1703. end;
  1704. Procedure TDiscoveryJSONToPas.CreateAPIClassImplementation;
  1705. Procedure StringRes(AValue : String);
  1706. Var
  1707. S : String;
  1708. begin
  1709. S:=MakePascalString(AValue,True);
  1710. S:=StringReplace(S,#13#10,'''#13#10''',[rfReplaceAll]);
  1711. S:=StringReplace(S,#10,'''#10''',[rfReplaceAll]);
  1712. S:=StringReplace(S,#13,'''#13''',[rfReplaceAll]);
  1713. SimpleMethodBody([Format('Result:=%s;',[S])]);
  1714. end;
  1715. Var
  1716. CN : String;
  1717. S : TSchema;
  1718. I : Integer;
  1719. begin
  1720. CN:=GetAPIClassName;
  1721. ClassHeader(CN);
  1722. AddLn('Class Function %s.APIName : String;',[CN]);
  1723. StringRes(Description.name);
  1724. AddLn('Class Function %s.APIVersion : String;',[CN]);
  1725. StringRes(Description.version);
  1726. AddLn('Class Function %s.APIRevision : String;',[CN]);
  1727. StringRes(Description.revision);
  1728. AddLn('Class Function %s.APIID : String;',[CN]);
  1729. StringRes(Description.id);
  1730. AddLn('Class Function %s.APITitle : String;',[CN]);
  1731. StringRes(Description.Title);
  1732. AddLn('Class Function %s.APIDescription : String;',[CN]);
  1733. StringRes(Description.Description);
  1734. AddLn('Class Function %s.APIOwnerDomain : String;',[CN]);
  1735. StringRes(Description.ownerDomain);
  1736. AddLn('Class Function %s.APIOwnerName : String;',[CN]);
  1737. StringRes(Description.ownerName);
  1738. AddLn('Class Function %s.APIIcon16 : String;',[CN]);
  1739. StringRes(Description.icons.x16);
  1740. AddLn('Class Function %s.APIIcon32 : String;',[CN]);
  1741. StringRes(Description.icons.x32);
  1742. AddLn('Class Function %s.APIdocumentationLink : String;',[CN]);
  1743. StringRes(Description.documentationLink);
  1744. AddLn('Class Function %s.APIrootUrl : string;',[CN]);
  1745. StringRes(Description.rootUrl);
  1746. AddLn('Class Function %s.APIbasePath : string;',[CN]);
  1747. StringRes(Description.BasePath);
  1748. AddLn('Class Function %s.APIbaseURL : String;',[CN]);
  1749. StringRes(Description.BaseURL);
  1750. AddLn('Class Function %s.APIProtocol : string;',[CN]);
  1751. StringRes(Description.protocol);
  1752. AddLn('Class Function %s.APIservicePath : string;',[CN]);
  1753. StringRes(Description.servicePath);
  1754. AddLn('Class Function %s.APIbatchPath : String;',[CN]);
  1755. StringRes(Description.batchPath);
  1756. AddLn('Class Function %s.APIAuthScopes : TScopeInfoArray;',[CN]);
  1757. Addln('');
  1758. AddLn('begin');
  1759. IncIndent;
  1760. if not (Assigned(Description.Auth) and Assigned(Description.Auth.oauth2)) then
  1761. AddLn('SetLength(Result,0);')
  1762. else
  1763. begin
  1764. AddLn('SetLength(Result,%d);',[Length(Description.Auth.oauth2.Scopes)]);
  1765. For I:=0 to Length(Description.Auth.oauth2.Scopes)-1 do
  1766. begin
  1767. S:=Description.Auth.oauth2.Scopes[i];
  1768. AddLn('Result[%d].Name:=%s;',[I,MakePascalString(S.Name,True)]);
  1769. AddLn('Result[%d].Description:=%s;',[I,MakePascalString(S.Description,True)]);
  1770. end;
  1771. end;
  1772. Addln('');
  1773. DecIndent;
  1774. Addln('end;');
  1775. Addln('');
  1776. AddLn('Class Function %s.APINeedsAuth : Boolean;',[CN]);
  1777. SimpleMethodBody([Format('Result:=%s;',[BoolToStr(Assigned(Description.Auth) and Assigned(Description.Auth.oauth2),'True','False')])]);
  1778. AddLn('Class Procedure %s.RegisterAPIResources;',[CN]);
  1779. Addln('');
  1780. AddLn('begin');
  1781. IncIndent;
  1782. For I:=0 to FTypes.Count-1 do
  1783. if FTypes[i].DataType=dtClass then
  1784. AddLn('%s.RegisterObject;',[FTypes[i].PascalName]);
  1785. DecIndent;
  1786. Addln('end;');
  1787. Addln('');
  1788. CreateResourceAPIFunctionImplementations(GetAPIClassName,'',Description.resources);
  1789. end;
  1790. Procedure TDiscoveryJSONToPas.CreateResourceAPIFunctionImplementations(Const AClassName : String; Const APrefix : String; Resources : TSchemas);
  1791. Var
  1792. RN,CN,RCN : String;
  1793. R : TSchema;
  1794. begin
  1795. CN:=AClassName;
  1796. For R in Resources do
  1797. begin
  1798. if Assigned(R.Resources) then
  1799. CreateResourceAPIFunctionImplementations(CN,ConstructResourcePrefix(APrefix,R),R.Resources);
  1800. RN:=APrefix+PrettyPrint(R.Name);
  1801. RCN:=R.TypeName;
  1802. AddLn('');
  1803. AddLn('Function %s.Get%sInstance : %s;',[CN,RN,RCN]);
  1804. AddLn('');
  1805. AddLn('begin');
  1806. IncIndent;
  1807. AddLn('if (F%sInstance=Nil) then',[RN]);
  1808. IncIndent;
  1809. AddLn('F%sInstance:=Create%sResource;',[RN,RN]);
  1810. DecIndent;
  1811. AddLn('Result:=F%sInstance;',[RN]);
  1812. DecIndent;
  1813. AddLn('end;');
  1814. AddLn('');
  1815. AddLn('Function %s.Create%sResource : %s;',[CN,RN,RCN]);
  1816. SimpleMethodBody([Format('Result:=Create%sResource(Self);',[RN])]);
  1817. AddLn('');
  1818. AddLn('Function %s.Create%sResource(AOwner : TComponent) : %s;',[CN,RN,RCN]);
  1819. SimpleMethodBody([Format('Result:=%s.Create(AOwner);',[RCN]),
  1820. 'Result.API:=Self.API;']);
  1821. AddLn('');
  1822. end;
  1823. end;
  1824. Procedure TDiscoveryJSONToPas.Execute;
  1825. begin
  1826. Source.Clear;
  1827. Addln('unit '+outputunitname+';');
  1828. CreateHeader;
  1829. FTypes:=TTypeDefs.Create(TTypeDef);
  1830. try
  1831. CollectTypes;
  1832. CreateInterface;
  1833. AddLn('');
  1834. AddLn('implementation');
  1835. AddLn('');
  1836. CreateImplementation;
  1837. Addln('');
  1838. AddLn('initialization');
  1839. Addln(' %s.RegisterAPI;',[GetAPIClassName]);
  1840. finally
  1841. FTypes.Free;
  1842. end;
  1843. AddLn('end.');
  1844. end;
  1845. Class Procedure TDiscoveryJSONToPas.RegisterAllObjects;
  1846. begin
  1847. TGoogleIcons.RegisterObject;
  1848. TGoogleAuth2.RegisterObject;
  1849. TGoogleAuth.RegisterObject;
  1850. TArrayPropertyDef.RegisterObject;
  1851. TPropertyDef.RegisterObject;
  1852. TSchema.RegisterObject;
  1853. TGoogleRestDescription.RegisterObject;
  1854. TAnnotations.RegisterObject;
  1855. TRestMethod.RegisterObject;
  1856. TRestMethodParam.RegisterObject;
  1857. TMediaUpload.RegisterObject;
  1858. TMediaUploadProtocols.RegisterObject;
  1859. TMediaUploadProtocolsSimple.RegisterObject;
  1860. TMediaUploadProtocolsResumable.RegisterObject;
  1861. TRequest.RegisterObject;
  1862. TResponse.RegisterObject;
  1863. end;
  1864. end.