fpcgdbcoll.pp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2007 by Michael Van Canneyt, member of the
  4. Free Pascal development team
  5. Data Dictionary Code Generator Implementation.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit fpcgdbcoll;
  13. {$mode objfpc}{$H+}
  14. interface
  15. uses
  16. Classes, SysUtils, db, fpddcodegen;
  17. Type
  18. TListMode = (lmNone,lmList,lmObjectList,lmCollection,lmDBCollection);
  19. TClassOption = (coCreateLoader,coUseFieldMap,coCreateArrayProperty,coCreateAssign);
  20. TClassOptions = Set of TClassOption;
  21. { TDBCollOptions }
  22. TDBCollOptions = Class(TClassCodeGeneratorOptions)
  23. private
  24. FClassOptions: TClassOptions;
  25. FListMode: TListMode;
  26. FListAncestorName: String;
  27. FListClassName: String;
  28. FArrayPropName: String;
  29. FMapAncestorName: String;
  30. FMapClassName: String;
  31. function GetArrayPropName: String;
  32. function GetListClassName: String;
  33. function GetMapName: String;
  34. procedure SetArrayPropName(const AValue: String);
  35. procedure SetListAncestorName(const AValue: String);
  36. procedure SetListClassName(const AValue: String);
  37. procedure SetListMode(const AValue: TListMode);
  38. procedure SetMapAncestorName(const AValue: String);
  39. procedure SetMapClassName(const AValue: String);
  40. Public
  41. Constructor Create; override;
  42. Procedure Assign(ASource : TPersistent); override;
  43. Function CreateLoader : Boolean;
  44. Function UseFieldMap : Boolean;
  45. Function CreateArrayProperty : Boolean;
  46. Function CreateAssign : Boolean;
  47. Published
  48. Property ClassOptions : TClassOptions Read FClassOptions Write FClassOptions;
  49. Property ListMode : TListMode Read FListMode Write SetListMode;
  50. Property ListAncestorName : String Read FListAncestorName Write SetListAncestorName;
  51. Property ListClassName : String Read GetListClassName Write SetListClassName;
  52. Property MapAncestorName : String Read FMapAncestorName Write SetMapAncestorName;
  53. Property MapClassName : String Read GetMapName Write SetMapClassName;
  54. Property ArrayPropName : String Read GetArrayPropName Write SetArrayPropName;
  55. Property AncestorClass;
  56. end;
  57. { TDDDBCollCodeGenerator }
  58. TDDDBCollCodeGenerator = Class(TDDClassCodeGenerator)
  59. procedure CreateObjectAssign(Strings: TStrings;
  60. const ObjectClassName: String);
  61. private
  62. function GetOpt: TDBColLOptions;
  63. Protected
  64. // Not to be overridden.
  65. procedure CreateFieldMapImplementation(Strings: TStrings; const ObjectClassName, MapClassName: String);
  66. procedure CreateListImplementation(Strings: TStrings; ListMode: TListMode; const ObjectClassName, ListClassName: String);
  67. procedure WriteFieldMapAssign(Strings: TStrings; F: TFieldPropDef);
  68. procedure WriteMapInitFields(Strings: TStrings; const ObjectClassName, MapClassName: String);
  69. procedure WriteListLoad(Strings: TStrings; ListMode: TListMode; const ObjectClassName, ListClassName: String; FromMap: Boolean);
  70. procedure WriteListAddObject(Strings: TStrings; ListMode: TListMode; const InstanceName, ObjectClassName: String);
  71. // Overrides of parent objects
  72. Function GetInterfaceUsesClause : string; override;
  73. Procedure DoGenerateInterface(Strings: TStrings); override;
  74. Procedure DoGenerateImplementation(Strings: TStrings); override;
  75. procedure WriteVisibilityStart(V: TVisibility; Strings: TStrings); override;
  76. procedure CreateImplementation(Strings: TStrings); override;
  77. Class Function NeedsFieldDefs : Boolean; override;
  78. Function CreateOptions : TCodeGeneratorOptions; override;
  79. //
  80. // New methods
  81. //
  82. // Override to add declarations to list declaration
  83. procedure DoCreateListDeclaration(Strings: TStrings; ListMode: TListMode; const ObjectClassName, ListClassName, ListAncestorName: String); virtual;
  84. // Override to add declarations to fieldmap declaration
  85. procedure DoCreateFieldMapDeclaration(Strings: TStrings; const ObjectClassName,MapClassName, MapAncestorName: String); virtual;
  86. // Override to add statements to the FieldMap Load implementation
  87. procedure DoWriteMapLoad(Strings: TStrings; const ObjectClassName, MapClassName: String); virtual;
  88. // Override to add statements to the FieldMap LoadObject implementation
  89. procedure DoWriteMapLoadObject(Strings: TStrings; const ObjectClassName, MapClassName: String);virtual;
  90. // Create an object that should be added to the list.
  91. procedure WriteListCreateObject(Strings: TStrings; ListMode: TListMode; const InstanceName, ObjectClassName: String);
  92. // Write LoadFromDataset implementation for List object
  93. procedure WriteListLoadFromDataset(Strings: TStrings; ListMode: TListMode; const ObjectClassName, ListClassName: String);
  94. // Write LoadFromMap implementation for List object
  95. procedure WriteListLoadFromMap(Strings: TStrings; ListMode: TListMode; const ObjectClassName, ListClassName: String);
  96. // Object load from map;
  97. procedure CreateObjectLoadFromMap(Strings: TStrings; const ObjectClassName: String); virtual;
  98. // Create assign statement for a property from a dataset field, in object itself (not in map).
  99. procedure WriteFieldDatasetAssign(Strings: TStrings; F: TFieldPropDef); virtual;
  100. // Copy a property from one instance to another in Assign()
  101. procedure WriteFieldAssign(Strings: TStrings; F: TFieldPropDef); virtual;
  102. // Code to Load object from fataset (should check usefieldmap)
  103. procedure CreateObjectLoadFromDataset(Strings: TStrings; const ObjectClassName: String); virtual;
  104. Public
  105. procedure CreateFieldMapDeclaration(Strings: TStrings; const ObjectClassName,MapClassName,
  106. MapAncestorName: String);
  107. procedure CreateListDeclaration(Strings: TStrings; ListMode: TListMode;
  108. const ObjectClassName, ListClassName, ListAncestorName: String);
  109. Property DBCollOptions : TDBColLOptions Read GetOpt;
  110. end;
  111. implementation
  112. { TDBCollOptions }
  113. procedure TDBCollOptions.SetListMode(const AValue: TListMode);
  114. begin
  115. if FListMode=AValue then exit;
  116. FListMode:=AValue;
  117. Case ListMode of
  118. lmNone :
  119. begin
  120. Exclude(FClassOptions,coCreateArrayProperty);
  121. end;
  122. lmList :
  123. begin
  124. AncestorClass:='TPersistent';
  125. ListAncestorName:='TList';
  126. end;
  127. lmObjectList :
  128. begin
  129. AncestorClass:='TPersistent';
  130. ListAncestorName:='TObjectList';
  131. end;
  132. lmCollection :
  133. begin
  134. AncestorClass:='TCollectionItem';
  135. ListAncestorName:='TCollection';
  136. end;
  137. lmDBCollection :
  138. begin
  139. AncestorClass:='TDBCollectionItem';
  140. ListAncestorName:='TDBCollection';
  141. Include(FClassoptions,coUseFieldMap);
  142. end;
  143. end;
  144. end;
  145. procedure TDBCollOptions.SetMapAncestorName(const AValue: String);
  146. begin
  147. CheckIdentifier(AValue,True);
  148. FMapAncestorName:=AValue;
  149. end;
  150. procedure TDBCollOptions.SetMapClassName(const AValue: String);
  151. begin
  152. CheckIdentifier(AValue,True);
  153. FMapClassName:=AValue;
  154. end;
  155. function TDBCollOptions.GetListClassName: String;
  156. begin
  157. Result:=FListClassName;
  158. If (Result='') then
  159. Result:=ObjectClassName+'List';
  160. end;
  161. function TDBCollOptions.GetArrayPropName: String;
  162. begin
  163. Result:=FArrayPropName;
  164. If (Result='') then
  165. begin
  166. Result:=ObjectClassName;
  167. If (Result<>'') and (Upcase(Result[1])='T') then
  168. Delete(Result,1,1);
  169. Result:=Result+'s';
  170. end;
  171. end;
  172. function TDBCollOptions.GetMapName: String;
  173. begin
  174. Result:=FMapClassName;
  175. If (Result='') then
  176. Result:=ObjectClassName+'Map';
  177. end;
  178. procedure TDBCollOptions.SetArrayPropName(const AValue: String);
  179. begin
  180. CheckIdentifier(AValue,True);
  181. FArrayPropName:=AValue;
  182. end;
  183. procedure TDBCollOptions.SetListAncestorName(const AValue: String);
  184. begin
  185. CheckIdentifier(AValue,True);
  186. FListAncestorName:=AValue;
  187. end;
  188. procedure TDBCollOptions.SetListClassName(const AValue: String);
  189. begin
  190. CheckIdentifier(AValue,True);
  191. FListClassName:=AValue;
  192. end;
  193. constructor TDBCollOptions.Create;
  194. begin
  195. inherited Create;
  196. FClassOptions:=[coCreateLoader,coUseFieldMap,coCreateAssign];
  197. AncestorClass:='TPersistent';
  198. FListAncestorName:='TList';
  199. ObjectClassName:='TMyObject';
  200. FMapAncestorName:='TFieldMap';
  201. end;
  202. procedure TDBCollOptions.Assign(ASource: TPersistent);
  203. Var
  204. DC : TDBCollOptions;
  205. begin
  206. If ASource is TDBCollOptions then
  207. begin
  208. DC:=ASource as TDBCollOptions;
  209. ListMode:=DC.ListMode;
  210. FClassOptions:=DC.FClassOptions;
  211. FListAncestorName:=DC.FListAncestorName;
  212. FListClassName:=DC.FListClassName;
  213. FMapAncestorName:=DC.FMapAncestorName;
  214. FMapClassName:=DC.FMapClassName;
  215. FArrayPropName:=DC.FArrayPropName;
  216. end;
  217. inherited Assign(ASource);
  218. end;
  219. function TDBCollOptions.CreateLoader: Boolean;
  220. begin
  221. Result:=coCreateLoader in ClassOptions;
  222. end;
  223. function TDBCollOptions.UseFieldMap: Boolean;
  224. begin
  225. Result:=coUseFieldMap in ClassOptions;
  226. end;
  227. function TDBCollOptions.CreateArrayProperty: Boolean;
  228. begin
  229. Result:=coCreateArrayProperty in ClassOptions;
  230. end;
  231. function TDBCollOptions.CreateAssign: Boolean;
  232. begin
  233. Result:=coCreateAssign in ClassOptions;
  234. end;
  235. { TDDDBCollCodeGenerator }
  236. function TDDDBCollCodeGenerator.GetOpt: TDBColLOptions;
  237. begin
  238. Result:=CodeOptions as TDBColLOptions
  239. end;
  240. procedure TDDDBCollCodeGenerator.DoGenerateInterface(Strings: TStrings);
  241. begin
  242. inherited DoGenerateInterface(Strings);
  243. With DBCollOptions do
  244. begin
  245. If CreateLoader then
  246. begin
  247. if UseFieldMap then
  248. CreateFieldMapDeclaration(Strings,ObjectClassName,MapClassName,MapAncestorName);
  249. end;
  250. if ListMode<>lmNone then
  251. CreateListDeclaration(Strings,ListMode,ObjectClassName,ListClassName,ListAncestorName);
  252. end;
  253. end;
  254. procedure TDDDBCollCodeGenerator.DoGenerateImplementation(Strings: TStrings);
  255. begin
  256. inherited DoGenerateImplementation(Strings);
  257. With DBCollOptions do
  258. begin
  259. If CreateLoader then
  260. If UseFieldMap then
  261. CreateFieldMapImplementation(Strings,ObjectClassName,MapClassName);
  262. if ListMode<>lmNone then
  263. CreateListImplementation(Strings,ListMode,ObjectClassName,ListClassName);
  264. end;
  265. end;
  266. procedure TDDDBCollCodeGenerator.WriteVisibilityStart(V: TVisibility;
  267. Strings: TStrings);
  268. begin
  269. inherited WriteVisibilityStart(V, Strings);
  270. If (V=vPublic) then
  271. With DBCollOptions do
  272. begin
  273. If CreateLoader and (ListMode in [lmList,lmObjectList,lmCollection]) then
  274. begin
  275. If UseFieldMap Then
  276. AddLn(Strings,'Procedure LoadFromMap(Map : TFieldMap);');
  277. AddLn(Strings,'Procedure LoadFromDataset(ADataset : TDataset);');
  278. end;
  279. If CreateAssign then
  280. AddLn(Strings,'Procedure Assign(ASource : TPersistent); override;');
  281. end;
  282. end;
  283. procedure TDDDBCollCodeGenerator.CreateImplementation(Strings: TStrings);
  284. Var
  285. S : String;
  286. begin
  287. inherited CreateImplementation(Strings);
  288. With DBCOlloptions do
  289. begin
  290. If CreateLoader and (ListMode in [lmList,lmObjectList,lmCollection]) then
  291. begin
  292. if UseFieldMap then
  293. begin
  294. S:=Format('Procedure %s.LoadFromMap(Map : TFieldMap);',[ObjectClassName]);
  295. BeginMethod(Strings,S);
  296. CreateObjectLoadFromMap(Strings,ObjectClassName);
  297. EndMethod(Strings,S);
  298. end;
  299. S:=Format('Procedure %s.LoadFromDataset(ADataset : TDataset);',[ObjectClassName]);
  300. BeginMethod(Strings,S);
  301. CreateObjectLoadFromDataset(Strings,ObjectClassName);
  302. EndMethod(Strings,S);
  303. end;
  304. If CreateAssign then
  305. begin
  306. S:=Format('Procedure %s.Assign(ASource : TPersistent);',[ObjectClassName]);
  307. BeginMethod(Strings,S);
  308. CreateObjectAssign(Strings,ObjectClassName);
  309. EndMethod(Strings,S);
  310. end;
  311. end;
  312. end;
  313. procedure TDDDBCollCodeGenerator.CreateObjectAssign(Strings : TStrings; Const ObjectClassName : String);
  314. Var
  315. I : Integer;
  316. F : TFieldPropDef;
  317. begin
  318. AddLn(Strings,'var');
  319. IncIndent;
  320. Try
  321. AddLn(Strings,'O : %s ;',[ObjectClassName]);
  322. Finally
  323. DecIndent;
  324. end;
  325. Addln(Strings,'begin');
  326. IncIndent;
  327. Try
  328. AddLn(Strings,'If (ASource is %s) then',[ObjectClassName]);
  329. IncIndent;
  330. Try
  331. Addln(Strings,'begin');
  332. Addln(Strings,'O:=(ASource as %s);',[ObjectClassName]);
  333. For I:=0 to Fields.Count-1 do
  334. begin
  335. F:=Fields[i];
  336. If F.Enabled Then
  337. WriteFieldAssign(Strings,F);
  338. end;
  339. Addln(Strings,'end');
  340. Finally
  341. DecIndent;
  342. end;
  343. AddLn(Strings,'else');
  344. IncIndent;
  345. Try
  346. AddLn(Strings,'Inherited;');
  347. Finally
  348. DecIndent;
  349. end;
  350. Finally
  351. DecIndent;
  352. end;
  353. end;
  354. procedure TDDDBCollCodeGenerator.WriteFieldAssign(Strings : TStrings; F : TFieldPropDef);
  355. Var
  356. S : String;
  357. begin
  358. Case F.PropertyType of
  359. ptStream: S:=Format('%s.CopyFrom(O.%s,0);',[F.ObjPasReadDef,F.ObjPasReadDef]);
  360. ptTStrings: S:=Format('%s.Assign(O.%s,0);',[F.ObjPasReadDef,F.ObjPasReadDef]);
  361. ptCustom: S:=Format('// Custom code to assign %s from O.%s',[F.ObjPasReadDef,F.ObjPasReadDef]);
  362. else
  363. S:=Format('%s:=O.%s;',[F.ObjPasReadDef,F.ObjPasReadDef]);
  364. end;
  365. AddLn(Strings,S);
  366. end;
  367. procedure TDDDBCollCodeGenerator.CreateObjectLoadFromMap(Strings : TStrings; Const ObjectClassName : String);
  368. begin
  369. Addln(Strings,'begin');
  370. IncIndent;
  371. Try
  372. AddLn(Strings,'Map.LoadObject(Self);');
  373. Finally
  374. DecIndent;
  375. end;
  376. end;
  377. procedure TDDDBCollCodeGenerator.CreateObjectLoadFromDataset(Strings : TStrings; Const ObjectClassName : String);
  378. Var
  379. I : Integer;
  380. begin
  381. AddLn(Strings,'begin');
  382. Incindent;
  383. try
  384. If DBColloptions.UseFieldMap then
  385. begin
  386. AddLn(Strings,'With %s.Create(ADataset) do',[DBCollOptions.MapClassName]);
  387. IncIndent;
  388. Try
  389. Addln(Strings,'try');
  390. IncIndent;
  391. Try
  392. Addln(Strings,'LoadObject(Self);');
  393. Finally
  394. DecIndent;
  395. end;
  396. Addln(Strings,'Finally');
  397. IncIndent;
  398. Try
  399. Addln(Strings,'Free;');
  400. Finally
  401. DecIndent;
  402. end;
  403. Addln(Strings,'end;');
  404. Finally
  405. Decindent;
  406. end;
  407. end
  408. else
  409. begin
  410. AddLn(Strings,'With ADataset do');
  411. IncIndent;
  412. Try
  413. AddLn(Strings,'begin');
  414. For I:=0 to Fields.Count-1 do
  415. If Fields[i].Enabled then
  416. WriteFieldDatasetAssign(Strings,Fields[i]);
  417. AddLn(Strings,'end;');
  418. Finally
  419. DecIndent;
  420. end;
  421. end;
  422. Finally
  423. Decindent;
  424. end;
  425. end;
  426. procedure TDDDBCollCodeGenerator.WriteFieldDatasetAssign(Strings : TStrings; F : TFieldPropDef);
  427. Var
  428. FN,PN,S,R : String;
  429. begin
  430. PN:=F.PropertyName;
  431. FN:=F.FieldName;
  432. Case F.PropertyType of
  433. ptBoolean :
  434. S:='AsBoolean';
  435. ptShortint, ptByte,
  436. ptSmallInt, ptWord,
  437. ptLongint, ptCardinal :
  438. S:='AsInteger';
  439. ptInt64, ptQWord:
  440. If F.FieldType=ftLargeInt then
  441. R:=Format('%s:=(FieldByName(%s) as TLargeIntField).AsLargeInt;',[PN,CreateString(FN)])
  442. else
  443. S:='AsInteger';
  444. ptShortString, ptAnsiString, ptWideString :
  445. S:='AsString';
  446. ptSingle, ptDouble, ptExtended, ptComp :
  447. S:='AsFloat';
  448. ptCurrency :
  449. S:='AsCurrency';
  450. ptDateTime :
  451. S:='AsDateTime';
  452. ptEnumerated :
  453. R:=Format('Integer(%s):=FieldByName(%s).AsInteger;',[PN,CreateString(FN)]);
  454. ptSet :
  455. S:=Format('// Add custom set loading code here for %s from %s',[PN,FN]);
  456. ptStream :
  457. R:=Format('FieldByName(%s).SaveToStream(%s);',[CreateString(FN),PN]);
  458. ptTStrings :
  459. R:=Format('%s.Text:=FieldByName(%s).AsString;',[PN,CreateString(FN),PN]);
  460. ptCustom :
  461. R:=Format('// Add custom loading code here for %s from %s',[PN,FN]);
  462. end;
  463. If (S<>'') then
  464. R:=Format('%s:=FieldByName(%s).%s;',[PN,CreateString(FN),s]);
  465. AddLn(Strings,R);
  466. end;
  467. { FieldMap interface generation routines}
  468. procedure TDDDBCollCodeGenerator.CreateFieldMapDeclaration(Strings : TStrings;
  469. Const ObjectClassName,MapClassName,MapAncestorName : String);
  470. begin
  471. Addln(Strings);
  472. IncIndent;
  473. try
  474. Addln(Strings,'{ %s }',[MapClassName]);
  475. Addln(Strings);
  476. Addln(Strings,'%s = Class(%s)',[MapClassName,MapAncestorName]);
  477. DoCreateFieldMapDeclaration(Strings,ObjectClassName,MapClassName,MapAncestorName);
  478. AddLn(Strings,'end;');
  479. Finally
  480. DecIndent;
  481. end;
  482. end;
  483. procedure TDDDBCollCodeGenerator.DoCreateFieldMapDeclaration(Strings : TStrings;
  484. Const ObjectClassName,MapClassName,MapAncestorName : String);
  485. Var
  486. I : Integer;
  487. F : TFieldPropDef;
  488. begin
  489. AddLn(Strings,'Private');
  490. IncIndent;
  491. Try
  492. For I:=0 to Fields.Count-1 do
  493. begin
  494. F:=Fields[I];
  495. If F.Enabled then
  496. AddLn(Strings,'F%s : TField;',[F.FieldName]);
  497. end;
  498. AddLn(Strings,'Procedure DoLoad(AObject : %s);',[ObjectClassName]);
  499. Finally
  500. DecIndent;
  501. end;
  502. AddLn(Strings,'Public');
  503. IncIndent;
  504. Try
  505. AddLn(Strings,'Procedure InitFields; Override;');
  506. AddLn(Strings,'Procedure LoadObject(AObject : TObject); Override;');
  507. Finally
  508. DecIndent;
  509. end;
  510. end;
  511. { FieldMap implementation generation routines}
  512. procedure TDDDBCollCodeGenerator.CreateFieldMapImplementation(Strings : TStrings;
  513. Const ObjectClassName,MapClassName : String);
  514. Var
  515. S : String;
  516. begin
  517. AddLn(Strings,' { %s }',[MapClassName]);
  518. AddLn(Strings);
  519. S:=Format('Procedure %s.DoLoad(AObject : %s);',[MapClassName,ObjectClassName]);
  520. BeginMethod(Strings,S);
  521. Try
  522. DoWriteMapLoad(Strings,ObjectClassName,MapClassName);
  523. Finally
  524. EndMethod(Strings,S);
  525. end;
  526. S:=Format('Procedure %s.LoadObject(AObject : TObject);',[MapClassName]);
  527. BeginMethod(Strings,S);
  528. Try
  529. DoWriteMapLoadObject(Strings,ObjectClassName,MapClassName);
  530. Finally
  531. EndMethod(Strings,S);
  532. end;
  533. S:=Format('Procedure %s.InitFields;',[MapClassName]);
  534. BeginMethod(Strings,S);
  535. Try
  536. WriteMapInitFields(Strings,ObjectClassName,MapClassName);
  537. Finally
  538. EndMethod(Strings,S);
  539. end;
  540. end;
  541. procedure TDDDBCollCodeGenerator.DoWriteMapLoad(Strings : TStrings; COnst ObjectClassName,MapClassName : String);
  542. Var
  543. I : Integer;
  544. begin
  545. AddLn(Strings,'begin');
  546. IncIndent;
  547. try
  548. AddLn(Strings,'With AObject do');
  549. IncIndent;
  550. try
  551. AddLn(Strings,'begin');
  552. For I:=0 to Fields.Count-1 do
  553. If Fields[i].Enabled then
  554. WriteFieldMapAssign(Strings,Fields[i]);
  555. AddLn(Strings,'end;');
  556. finally
  557. DecIndent;
  558. end;
  559. finally
  560. DecIndent;
  561. end;
  562. end;
  563. procedure TDDDBCollCodeGenerator.DoWriteMapLoadObject(Strings : TStrings; Const ObjectClassName,MapClassName : String);
  564. begin
  565. Addln(Strings,'begin');
  566. IncIndent;
  567. try
  568. Addln(Strings,'DoLoad(AObject as %s);',[ObjectClassName]);
  569. finally
  570. DecIndent;
  571. end;
  572. end;
  573. procedure TDDDBCollCodeGenerator.WriteFieldMapAssign(Strings : TStrings; F : TFieldPropDef);
  574. Var
  575. FN,PN,S : String;
  576. begin
  577. PN:=F.PropertyName;
  578. FN:='Self.F'+F.FieldName;
  579. Case F.PropertyType of
  580. ptBoolean :
  581. S:=Format('%s:=GetFromField(%s,%s);',[PN,FN,PN]);
  582. ptShortint, ptByte,
  583. ptSmallInt, ptWord,
  584. ptLongint, ptCardinal :
  585. S:=Format('%s:=GetFromField(%s,%s);',[PN,FN,PN]);
  586. ptInt64, ptQWord,
  587. ptShortString, ptAnsiString, ptWideString :
  588. S:=Format('%s:=GetFromField(%s,%s);',[PN,FN,PN]);
  589. ptSingle, ptDouble, ptExtended, ptComp, ptCurrency :
  590. S:=Format('%s:=GetFromField(%s,%s);',[PN,FN,PN]);
  591. ptDateTime :
  592. S:=Format('%s:=GetFromField(%s,%s);',[PN,FN,PN]);
  593. ptEnumerated :
  594. S:=Format('Integer(%s):=GetFromField(%s,Ord(%s));',[PN,FN,PN]);
  595. ptSet :
  596. S:=Format('// Add custom set loading code here for %s from %s',[PN,FN]);
  597. ptStream :
  598. S:=Format('%s.SaveToStream(%s);',[FN,PN]);
  599. ptTStrings :
  600. S:=Format('%s.Text:=GetFromField(%s,%s.Text)',[PN,FN,PN]);
  601. ptCustom :
  602. S:=Format('// Add custom loading code here for %s from %s',[PN,FN]);
  603. end;
  604. AddLn(Strings,S);
  605. end;
  606. procedure TDDDBCollCodeGenerator.WriteMapInitFields(Strings : TStrings; COnst ObjectClassName,MapClassName : String);
  607. Var
  608. I: Integer;
  609. F : TFieldPropDef;
  610. begin
  611. AddLn(Strings,'begin');
  612. IncIndent;
  613. try
  614. For I:=0 to Fields.Count-1 Do
  615. begin
  616. F:=Fields[i];
  617. If F.Enabled then
  618. AddLn(Strings,'F%s:=FindField(%s);',[F.FieldName,CreateString(F.FieldName)]);
  619. end;
  620. Finally
  621. DecIndent;
  622. end;
  623. end;
  624. function TDDDBCollCodeGenerator.GetInterfaceUsesClause: string;
  625. begin
  626. Result:=inherited GetInterfaceUsesClause;
  627. With DBColloptions do
  628. if CreateLoader or (ListMode=lmDBCollection) then
  629. begin
  630. If (Result<>'') then
  631. Result:=Result+', ';
  632. Result:=Result+'db';
  633. If (ListMode=lmObjectList) then
  634. Result:=Result+', contnrs';
  635. If UseFieldMap or (ListMode=lmDBCollection) then
  636. Result:=Result+', dbcoll';
  637. end;
  638. end;
  639. { List class generation routines }
  640. procedure TDDDBCollCodeGenerator.CreateListDeclaration(Strings : TStrings;
  641. ListMode : TListMode; Const ObjectClassName,ListClassName,ListAncestorName : String);
  642. begin
  643. IncIndent;
  644. try
  645. Addln(Strings);
  646. Addln(Strings,'{ %s }',[ListClassName]);
  647. Addln(Strings);
  648. Addln(Strings,'%s = Class(%s)',[ListClassName,ListAncestorName]);
  649. DoCreateListDeclaration(Strings,ListMode,ObjectClassName,ListClassName,ListAncestorName);
  650. AddLn(Strings,'end;');
  651. Finally
  652. DecIndent;
  653. end;
  654. end;
  655. procedure TDDDBCollCodeGenerator.DoCreateListDeclaration(Strings : TStrings;
  656. ListMode : TListMode; Const ObjectClassName,ListClassName,ListAncestorName : String);
  657. Var
  658. S : String;
  659. begin
  660. If DBCollOptions.CreateArrayProperty then
  661. begin
  662. AddLn(Strings,'Private');
  663. IncIndent;
  664. Try
  665. AddLn(Strings,'Function GetObj(Index : Integer) : %s;',[ObjectClassname]);
  666. AddLn(Strings,'Procedure SetObj(Index : Integer; AValue : %s);',[ObjectClassname]);
  667. Finally
  668. DecIndent;
  669. end;
  670. end;
  671. AddLn(Strings,'Public');
  672. IncIndent;
  673. Try
  674. If (ListMode in [lmList,lmObjectList,lmCollection]) and DBCollOptions.CreateLoader then
  675. begin
  676. If DBColloptions.UseFieldMap then
  677. AddLn(Strings,'Procedure LoadFromMap(Map : TFieldMap);');
  678. AddLn(Strings,'Procedure LoadFromDataset(Dataset : TDataset);');
  679. end
  680. Finally
  681. DecIndent;
  682. end;
  683. If DBCollOptions.CreateArrayProperty then
  684. begin
  685. IncIndent;
  686. Try
  687. S:=DBCollOptions.ArrayPropName;
  688. AddLn(Strings,'Property %s[Index : Integer] : %s Read GetObj Write SetObj; Default;',[S,ObjectClassname]);
  689. Finally
  690. DecIndent;
  691. end;
  692. end;
  693. end;
  694. procedure TDDDBCollCodeGenerator.CreateListImplementation(Strings : TStrings;
  695. ListMode : TListMode; Const ObjectClassName,ListClassName : String);
  696. Var
  697. S : String;
  698. begin
  699. If (ListMode in [lmList,lmObjectList,lmCollection]) and DBCollOptions.CreateLoader then
  700. begin
  701. AddLn(Strings,'{ %s }',[ListClassName]);
  702. If DBCollOptions.CreateArrayProperty then
  703. begin
  704. S:=Format('Function %s.GetObj(Index : Integer) : %s;',[ListClassName,ObjectClassname]);
  705. BeginMethod(Strings,S);
  706. AddLn(Strings,'begin');
  707. IncIndent;
  708. try
  709. AddLn(Strings,'Result:=%s(Items[Index]);',[ObjectClassname]);
  710. finally
  711. DecIndent;
  712. end;
  713. EndMethod(Strings,S);
  714. S:=Format('Procedure %s.SetObj(Index : Integer; AValue : %s);',[ListClassName,ObjectClassname]);
  715. BeginMethod(Strings,S);
  716. AddLn(Strings,'begin');
  717. IncIndent;
  718. try
  719. AddLn(Strings,'Items[Index]:=AValue;');
  720. finally
  721. DecIndent;
  722. end;
  723. EndMethod(Strings,S);
  724. end;
  725. If DBColloptions.UseFieldMap then
  726. begin
  727. AddLn(Strings);
  728. S:=Format('Procedure %s.LoadFromMap(Map : TFieldMap);',[ListClassName]);
  729. BeginMethod(Strings,S);
  730. WriteListLoadFromMap(Strings,Listmode,ObjectClassName,ListClassName);
  731. EndMethod(Strings,S);
  732. end;
  733. AddLn(Strings);
  734. S:=Format('Procedure %s.LoadFromDataset(Dataset : TDataset);',[ListClassName]);
  735. BeginMethod(Strings,S);
  736. WriteListLoadFromDataset(Strings,Listmode,ObjectClassName,ListClassName);
  737. EndMethod(Strings,S);
  738. end;
  739. end;
  740. procedure TDDDBCollCodeGenerator.WriteListLoadFromMap(Strings : TStrings; ListMode : TListMode; Const ObjectClassName,ListClassName : String);
  741. begin
  742. WriteListLoad(Strings,ListMode,ObjectClassName,ListClassName,True);
  743. end;
  744. procedure TDDDBCollCodeGenerator.WriteListLoadFromDataset(Strings : TStrings; ListMode : TListMode; Const ObjectClassName,ListClassName : String);
  745. Var
  746. M : String;
  747. begin
  748. If Not DBCollOptions.UseFieldMap then
  749. WriteListLoad(Strings,ListMode,ObjectClassName,ListClassName,False)
  750. else
  751. begin
  752. M:=DBCollOptions.MapClassName;
  753. AddLn(Strings);
  754. AddLn(Strings,'Var');
  755. IncIndent;
  756. try
  757. AddLn(Strings,'Map : %s;',[M]);
  758. Finally
  759. DecIndent;
  760. end;
  761. AddLn(Strings);
  762. AddLn(Strings,'begin');
  763. IncIndent;
  764. try
  765. AddLn(Strings,'Map:=%s.Create(Dataset);',[M]);
  766. AddLn(Strings,'Try');
  767. IncIndent;
  768. try
  769. AddLn(Strings,'LoadFromMap(Map);');
  770. finally
  771. DecIndent;
  772. end;
  773. AddLn(Strings,'Finally');
  774. IncIndent;
  775. try
  776. AddLn(Strings,'FreeAndNil(Map);');
  777. finally
  778. DecIndent;
  779. end;
  780. AddLn(Strings,'end;');
  781. finally
  782. DecIndent;
  783. end;
  784. end;
  785. end;
  786. procedure TDDDBCollCodeGenerator.WriteListLoad(Strings : TStrings; ListMode : TListMode; Const ObjectClassName,ListClassName : String; FromMap : Boolean);
  787. begin
  788. AddLn(Strings);
  789. AddLn(Strings,'Var');
  790. IncIndent;
  791. try
  792. AddLn(Strings,'Obj : %s;',[ObjectClassName]);
  793. Finally
  794. DecIndent;
  795. end;
  796. AddLn(Strings);
  797. AddLn(Strings,'begin');
  798. IncIndent;
  799. try
  800. If FromMap then
  801. begin
  802. AddLn(Strings,'With Map do');
  803. IncIndent;
  804. end;
  805. Try
  806. AddLn(Strings,'While not Dataset.EOF do');
  807. IncIndent;
  808. Try
  809. AddLn(Strings,'begin');
  810. WriteListCreateObject(Strings,ListMode,'Obj',ObjectClassName);
  811. AddLn(Strings,'Try');
  812. IncIndent;
  813. Try
  814. If FromMap then
  815. AddLn(Strings,'LoadObject(Obj);')
  816. else
  817. AddLn(Strings,'Obj.LoadFromDataset(Dataset);');
  818. WriteListAddObject(Strings,ListMode,'Obj',ObjectClassName);
  819. Finally
  820. DecIndent;
  821. end;
  822. AddLn(Strings,'Except');
  823. IncIndent;
  824. Try
  825. AddLn(Strings,'FreeAndNil(Obj);');
  826. AddLn(Strings,'Raise;');
  827. Finally
  828. DecIndent;
  829. end;
  830. AddLn(Strings,'end;');
  831. AddLn(Strings,'Dataset.Next;');
  832. AddLn(Strings,'end;');
  833. Finally
  834. DecIndent;
  835. end;
  836. finally
  837. If FromMap then
  838. DecIndent;
  839. end;
  840. finally
  841. DecIndent;
  842. end;
  843. end;
  844. procedure TDDDBCollCodeGenerator.WriteListCreateObject(Strings : TStrings; ListMode : TListMode; Const InstanceName,ObjectClassName : String);
  845. Var
  846. S : String;
  847. begin
  848. If ListMode in [lmList,lmObjectList] then
  849. S:=Format('%s:=%s.Create;',[InstanceName,ObjectClassName])
  850. else
  851. S:=Format('%s:=Self.Add as %s;',[InstanceName,ObjectClassName]);
  852. AddLn(Strings,S);
  853. end;
  854. procedure TDDDBCollCodeGenerator.WriteListAddObject(Strings : TStrings; ListMode : TListMode; Const InstanceName,ObjectClassName : String);
  855. Var
  856. S : String;
  857. begin
  858. If ListMode in [lmList,lmObjectList] then
  859. begin
  860. S:=Format('Add(%s);',[InstanceName]);
  861. AddLn(Strings,S);
  862. end;
  863. end;
  864. class function TDDDBCollCodeGenerator.NeedsFieldDefs: Boolean;
  865. begin
  866. Result:=True;
  867. end;
  868. function TDDDBCollCodeGenerator.CreateOptions: TCodeGeneratorOptions;
  869. begin
  870. Result:=TDBCollOptions.Create;
  871. end;
  872. Initialization
  873. RegisterCodeGenerator('DBColl','Simple object/collection for the data',TDDDBCollCodeGenerator);
  874. Finalization
  875. UnRegisterCodeGenerator(TDDDBCollCodeGenerator);
  876. end.