fpcgfieldmap.pp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. {$IFNDEF FPC_DOTTEDUNITS}
  2. unit fpcgfieldmap;
  3. {$ENDIF FPC_DOTTEDUNITS}
  4. {
  5. This file is part of the Free Pascal run time library.
  6. Copyright (c) 1999-2022 by Michael van Canneyt and other members of the
  7. Free Pascal development team
  8. Fieldmap implementation
  9. See the file COPYING.FPC, included in this distribution,
  10. for details about the copyright.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. **********************************************************************}
  15. {$mode objfpc}{$H+}
  16. interface
  17. {$IFDEF FPC_DOTTEDUNITS}
  18. uses
  19. System.Classes, System.SysUtils, Data.CodeGen.Base;
  20. {$ELSE FPC_DOTTEDUNITS}
  21. uses
  22. Classes, SysUtils, fpddcodegen;
  23. {$ENDIF FPC_DOTTEDUNITS}
  24. Type
  25. { TGenFieldMapOptions }
  26. TFieldMapOption = (fmoPublicFields,fmoRequireFields,fmoLoadObject,fmoCreateParamMap,fmoSaveObject,fmoOverrideTransformString,fmoDefineArray,fmoDefineList);
  27. TListParent = (lpFPList,lpList,lpObjectList,lpFPObjectList,lpGenericList,lpFGLGenericList);
  28. TFieldMapOptions = Set of TFieldMapOption;
  29. TGenFieldMapOptions = Class(TClassCodeGeneratorOptions)
  30. Private
  31. FListParent: TListParent;
  32. FOptions: TFieldMapOptions;
  33. FMapClassName : String;
  34. FMapAncestorClassName : String;
  35. FParamMapClassName : String;
  36. FParamMapAncestorClassName : String;
  37. Protected
  38. function GetMapAncestorName: String; virtual;
  39. function GetMapName: String; virtual;
  40. procedure SetMapAncestorName(const aValue: String); virtual;
  41. procedure SetMapClassName(const aValue: String); virtual;
  42. function GetParamMapAncestorName: String;virtual;
  43. function GetParamMapName: String;virtual;
  44. procedure SetParamMapAncestorName(const aValue: String); virtual;
  45. procedure SetParamMapClassName(const aValue: String); virtual;
  46. Public
  47. Constructor Create; override;
  48. Procedure Assign(ASource: TPersistent); override;
  49. Property MapAncestorName : String Read GetMapAncestorName Write SetMapAncestorName;
  50. Property MapClassName : String Read GetMapName Write SetMapClassName;
  51. Property ParamMapAncestorName : String Read GetParamMapAncestorName Write SetParamMapAncestorName;
  52. Property ParamMapClassName : String Read GetParamMapName Write SetParamMapClassName;
  53. Property ListParent : TListParent Read FListParent Write FlistParent;
  54. Property AncestorClass;
  55. Published
  56. Property FieldMapOptions : TFieldMapOptions Read FOptions Write FOptions;
  57. end;
  58. { TDDDBFieldMapCodeGenerator }
  59. { TDDBaseFieldMapCodeGenerator }
  60. TDDBaseFieldMapCodeGenerator = Class(TDDClassCodeGenerator)
  61. private
  62. function GetOpt: TGenFieldMapOptions;
  63. Protected
  64. // Overrides;
  65. Function GetInterfaceUsesClause : string; override;
  66. Function CreateOptions : TCodeGeneratorOptions; override;
  67. // New methods
  68. function GetListParent: string; virtual;
  69. function GetListParentUnit: String; virtual;
  70. procedure CreateObjectListDeclaration(Strings: TStrings; const aObjectClassName: string);virtual;
  71. procedure CreateObjectListImplementation(Strings: TStrings; const aObjectClassName: string);virtual;
  72. procedure AddTransFormOverrideDeclarations(Strings: TStrings); virtual;
  73. procedure AddTransFormOverrideImplementations(Strings: TStrings; MapClassName: string); virtual;
  74. procedure WriteFillMethod(Strings: TStrings; const ObjectClassName, MapClassName: String); virtual;
  75. procedure WriteSaveMethod(Strings: TStrings; const ObjectClassName, MapClassName: String); virtual;
  76. procedure DoCreateFieldMapDeclaration(Strings: TStrings; const ObjectClassName,MapClassName, MapAncestorName: String); virtual;
  77. procedure DoCreateParamMapDeclaration(Strings: TStrings; const ObjectClassName,MapClassName, MapAncestorName: String); virtual;
  78. procedure WriteMapInitFields(Strings: TStrings; const ObjectClassName, MapClassName: String); virtual;
  79. procedure WriteParamMapInitParams(Strings: TStrings; const ObjectClassName, MapClassName: String); virtual;
  80. procedure CreateFieldMapImplementation(Strings: TStrings; const ObjectClassName, MapClassName: String);
  81. procedure CreateParamMapImplementation(Strings: TStrings; const ObjectClassName, MapClassName: String);
  82. procedure CreateObjectArrayDeclaration(Strings: TStrings; const aObjectClassName: string);
  83. Property FieldMapOpts : TGenFieldMapOptions Read Getopt;
  84. Public
  85. Class function NeedsFieldDefs: Boolean; override;
  86. procedure CreateFieldMapDeclaration(Strings: TStrings; const ObjectClassName,MapClassName, MapAncestorName: String);
  87. procedure CreateParamMapDeclaration(Strings: TStrings; const ObjectClassName,MapClassName, MapAncestorName: String); virtual;
  88. end;
  89. { TGenFieldMapCodeGenOptions }
  90. TGenFieldMapCodeGenOptions = class(TGenFieldMapOptions)
  91. Public
  92. constructor create; override;
  93. Published
  94. Property AncestorClass;
  95. Property MapClassName;
  96. Property MapAncestorName;
  97. Property ParamMapClassName;
  98. Property ParamMapAncestorName;
  99. Property ListParent;
  100. end;
  101. TDDDBFieldMapCodeGenerator = Class(TDDBaseFieldMapCodeGenerator)
  102. private
  103. Protected
  104. Function CreateOptions : TCodeGeneratorOptions; override;
  105. Procedure DoGenerateInterface(Strings: TStrings); override;
  106. Procedure DoGenerateImplementation(Strings: TStrings); override;
  107. Public
  108. Property FieldMapOpts;
  109. end;
  110. implementation
  111. {$IFDEF FPC_DOTTEDUNITS}
  112. uses System.TypInfo;
  113. {$ELSE FPC_DOTTEDUNITS}
  114. uses typinfo;
  115. {$ENDIF FPC_DOTTEDUNITS}
  116. { TGenFieldMapCodeGenOptions }
  117. constructor TGenFieldMapCodeGenOptions.create;
  118. begin
  119. inherited create;
  120. FieldMapOptions:=[fmoLoadObject]
  121. end;
  122. { TDDDBFieldMapCodeGenerator }
  123. function TDDBaseFieldMapCodeGenerator.GetOpt: TGenFieldMapOptions;
  124. begin
  125. Result:=CodeOptions as TGenFieldMapOptions;
  126. end;
  127. procedure TDDBaseFieldMapCodeGenerator.CreateObjectArrayDeclaration(Strings : TStrings; const aObjectClassName : string);
  128. begin
  129. IncIndent;
  130. AddLn(Strings,'%sArray = Array of %s;',[aObjectClassName,aObjectClassName]);
  131. Addln(Strings,'');
  132. DecIndent;
  133. end;
  134. function TDDBaseFieldMapCodeGenerator.GetListParent : string;
  135. begin
  136. case FieldMapOpts.ListParent of
  137. lpList,
  138. lpGenericList : Result:='TList';
  139. lpFGLGenericList :Result:='TFPGList';
  140. lpFPList : Result:='TFPList';
  141. lpFPObjectList : Result:='TFPObjectList';
  142. lpObjectList : Result:='TObjectList';
  143. end;
  144. end;
  145. function GetListClass(const aObjectClassName : string) : string;
  146. begin
  147. Result:=aObjectClassName+'List';
  148. end;
  149. procedure TDDBaseFieldMapCodeGenerator.CreateObjectListDeclaration(Strings : TStrings; const aObjectClassName : string);
  150. var
  151. lListClassName,lListParent : String;
  152. begin
  153. IncIndent;
  154. lListParent:=GetListParent;
  155. lListClassName:=GetListClass(aObjectClassName);
  156. Addln(Strings,'{ %s }',[lListClassName]);
  157. AddLn(Strings);
  158. if FieldMapOpts.ListParent=lpGenericList then
  159. AddLn(Strings,'%s = specialize %s<%s>;',[lListClassName,lListParent,aObjectClassName])
  160. else
  161. begin
  162. AddLn(Strings,'%s = Class(%s)',[lListClassName,lListParent]);
  163. AddLn(Strings,'Private');
  164. IncIndent;
  165. AddLn(Strings,'Function _GetObj(const aIndex : Integer) : %s;',[aObjectClassName]);
  166. AddLn(Strings,'Procedure _SetObj(const aIndex : Integer; const aValue : %s);',[aObjectClassName]);
  167. DecIndent;
  168. AddLn(Strings,'Public');
  169. IncIndent;
  170. AddLn(Strings,'Property Objects[aIndex : Integer] : %s Read _GetObj Write _SetObj; default;',[aObjectClassName]);
  171. DecIndent;
  172. AddLn(Strings,'end;');
  173. end;
  174. DecIndent;
  175. end;
  176. procedure TDDBaseFieldMapCodeGenerator.CreateObjectListImplementation(Strings : TStrings; const aObjectClassName : string);
  177. var
  178. S,lListClass : String;
  179. begin
  180. lListClass:=aObjectClassName+'List';
  181. if FieldMapOpts.ListParent=lpGenericList then
  182. Exit; // nothing to do.
  183. S:=Format('Function %s._GetObj(const aIndex : Integer) : %s;',[lListClass,aObjectClassName]);
  184. BeginMethod(Strings,S);
  185. AddLn(Strings,'begin');
  186. IncIndent;
  187. AddLn(Strings,'Result:=%s(Items[aIndex]);',[aObjectClassName]);
  188. DecIndent;
  189. EndMethod(Strings,S);
  190. S:=Format('Procedure %s._SetObj(const aIndex : Integer; const aValue : %s);',[lListClass,aObjectClassName]);
  191. BeginMethod(Strings,S);
  192. AddLn(Strings,'begin');
  193. IncIndent;
  194. AddLn(Strings,'Items[aIndex]:=aValue;');
  195. DecIndent;
  196. EndMethod(Strings,S);
  197. end;
  198. function TDDBaseFieldMapCodeGenerator.GetListParentUnit : String;
  199. begin
  200. Case FieldMapOpts.ListParent of
  201. lpFPObjectList,
  202. lpObjectList: Result:='contnrs';
  203. lpGenericList : Result:='Generics.Collections';
  204. lpFGLGenericList : Result:='fgl';
  205. else
  206. Result:='';
  207. end;
  208. end;
  209. function TDDBaseFieldMapCodeGenerator.GetInterfaceUsesClause: string;
  210. Var
  211. ListUnit : String;
  212. begin
  213. Result:=inherited GetInterfaceUsesClause;
  214. If (Result<>'') then
  215. Result:=Result+', db, fieldmap';
  216. if fmoDefineList in FieldMapOpts.FieldMapOptions then
  217. begin
  218. ListUnit:=GetListParentUnit;
  219. if ListUnit<>'' then
  220. Result:=Result+', '+ListUnit;
  221. end;
  222. end;
  223. procedure TDDDBFieldMapCodeGenerator.DoGenerateInterface(Strings: TStrings);
  224. begin
  225. inherited DoGenerateInterface(Strings);
  226. AddLn(Strings,'Type');
  227. if fmoDefineArray in FieldMapOpts.FieldMapOptions then
  228. CreateObjectArrayDeclaration(Strings,GetOpt.ObjectClassName);
  229. if fmoDefineList in FieldMapOpts.FieldMapOptions then
  230. CreateObjectListDeclaration(Strings,GetOpt.ObjectClassName);
  231. CreatefieldMapDeclaration(Strings,GetOpt.ObjectClassName,GetOpt.MapClassName,GetOpt.MapAncestorName);
  232. if fmoCreateParamMap in GetOpt.FieldMapOptions then
  233. CreateParamMapDeclaration(Strings,GetOpt.ObjectClassName,GetOpt.ParamMapClassName,GetOpt.ParamMapAncestorName);
  234. end;
  235. procedure TDDDBFieldMapCodeGenerator.DoGenerateImplementation(Strings: TStrings
  236. );
  237. begin
  238. inherited DoGenerateImplementation(Strings);
  239. if fmoDefineList in FieldMapOpts.FieldMapOptions then
  240. CreateObjectListImplementation(Strings,GetOpt.ObjectClassName);
  241. With FieldMapOpts do
  242. CreateFieldMapImplementation(Strings,ObjectClassName,MapClassName);
  243. if fmoCreateParamMap in GetOpt.FieldMapOptions then
  244. CreateParamMapImplementation(Strings,GetOpt.ObjectClassName,GetOpt.ParamMapClassName);
  245. end;
  246. Function TDDDBFieldMapCodeGenerator.CreateOptions : TCodeGeneratorOptions;
  247. begin
  248. Result:=TGenFieldMapCodeGenOptions.Create
  249. end;
  250. function TDDBaseFieldMapCodeGenerator.CreateOptions: TCodeGeneratorOptions;
  251. begin
  252. Result:=TGenFieldMapOptions.Create;
  253. end;
  254. procedure TDDBaseFieldMapCodeGenerator.AddTransFormOverrideDeclarations(Strings : TStrings);
  255. Procedure Decl(aType : string);
  256. begin
  257. AddLn(Strings,'function TransFormString(const aString: %s) : %s; override;',[aType,aType]);
  258. end;
  259. begin
  260. AddLn(Strings,'Protected');
  261. IncIndent;
  262. Decl('RawByteString');
  263. Decl('UnicodeString');
  264. Decl('WideString');
  265. DecIndent;
  266. end;
  267. procedure TDDBaseFieldMapCodeGenerator.AddTransFormOverrideImplementations(Strings : TStrings; MapClassName : string);
  268. Procedure Decl(aType : string);
  269. var
  270. S : String;
  271. begin
  272. S:=Format('function %s.TransFormString(const aString: %s) : %s; ',[MapClassName,aType,atype]);
  273. BeginMethod(Strings,S);
  274. AddLn(Strings,'begin');
  275. IncIndent;
  276. AddLn(Strings,'Result:=aString;');
  277. DecIndent;
  278. EndMethod(Strings,S);
  279. end;
  280. begin
  281. Decl('RawByteString');
  282. Decl('UnicodeString');
  283. Decl('WideString');
  284. end;
  285. procedure TDDBaseFieldMapCodeGenerator.DoCreateFieldMapDeclaration(
  286. Strings: TStrings; const ObjectClassName, MapClassName,
  287. MapAncestorName: String);
  288. Var
  289. I : Integer;
  290. F : TFieldPropDef;
  291. begin
  292. AddLn(Strings,'Private');
  293. IncIndent;
  294. Try
  295. For I:=0 to Fields.Count-1 do
  296. begin
  297. F:=Fields[I];
  298. If F.Enabled then
  299. AddLn(Strings,'F%s : TField;',[F.PropertyName]);
  300. end;
  301. Finally
  302. DecIndent;
  303. end;
  304. if fmoOverrideTransformString in FieldMapOpts.FieldMapOptions then
  305. AddTransFormOverrideDeclarations(Strings);
  306. AddLn(Strings,'Public');
  307. IncIndent;
  308. Try
  309. AddLn(Strings,'Procedure InitFields; Override;');
  310. if fmoLoadObject in FieldMapOpts.FieldMapOptions then
  311. begin
  312. AddLn(Strings,'Procedure Fill(aObject: %s); virtual;',[ObjectClassName]);
  313. AddLn(Strings,'Procedure LoadObject(aObject: TObject); override;');
  314. end;
  315. if fmoPublicFields in FieldMapOpts.FieldMapOptions then
  316. For I:=0 to Fields.Count-1 do
  317. begin
  318. F:=Fields[I];
  319. If F.Enabled then
  320. AddLn(Strings,'Property %s : TField read F%s;',[F.PropertyName,F.FieldName]);
  321. end;
  322. Finally
  323. DecIndent;
  324. end;
  325. end;
  326. procedure TDDBaseFieldMapCodeGenerator.DoCreateParamMapDeclaration(
  327. Strings: TStrings; const ObjectClassName, MapClassName,
  328. MapAncestorName: String);
  329. Var
  330. I : Integer;
  331. F : TFieldPropDef;
  332. begin
  333. AddLn(Strings,'Private');
  334. IncIndent;
  335. Try
  336. For I:=0 to Fields.Count-1 do
  337. begin
  338. F:=Fields[I];
  339. If F.Enabled then
  340. AddLn(Strings,'F%s : TParam;',[F.PropertyName]);
  341. end;
  342. Finally
  343. DecIndent;
  344. end;
  345. if fmoOverrideTransformString in FieldMapOpts.FieldMapOptions then
  346. AddTransFormOverrideDeclarations(Strings);
  347. AddLn(Strings,'Public');
  348. IncIndent;
  349. Try
  350. AddLn(Strings,'Procedure InitParams; Override;');
  351. if fmoLoadObject in FieldMapOpts.FieldMapOptions then
  352. begin
  353. AddLn(Strings,'Procedure Save(aObject: %s); virtual;',[ObjectClassName]);
  354. AddLn(Strings,'Procedure SaveObject(aObject: TObject); override;');
  355. end;
  356. if fmoPublicFields in FieldMapOpts.FieldMapOptions then
  357. For I:=0 to Fields.Count-1 do
  358. begin
  359. F:=Fields[I];
  360. If F.Enabled then
  361. AddLn(Strings,'Property %s : TParam read F%s;',[F.PropertyName,F.FieldName]);
  362. end;
  363. Finally
  364. DecIndent;
  365. end;
  366. end;
  367. procedure TDDBaseFieldMapCodeGenerator.CreateParamMapDeclaration(Strings: TStrings; const ObjectClassName,MapClassName, MapAncestorName: String);
  368. begin
  369. Addln(Strings);
  370. IncIndent;
  371. try
  372. Addln(Strings,'{ %s }',[MapClassName]);
  373. Addln(Strings);
  374. Addln(Strings,'%s = Class(%s)',[MapClassName,MapAncestorName]);
  375. DoCreateParamMapDeclaration(Strings,ObjectClassName,MapClassName,MapAncestorName);
  376. AddLn(Strings,'end;');
  377. Finally
  378. DecIndent;
  379. end;
  380. end;
  381. procedure TDDBaseFieldMapCodeGenerator.CreateFieldMapDeclaration(Strings: TStrings; const ObjectClassName, MapClassName, MapAncestorName: String);
  382. begin
  383. Addln(Strings);
  384. IncIndent;
  385. try
  386. Addln(Strings,'{ %s }',[MapClassName]);
  387. Addln(Strings);
  388. Addln(Strings,'%s = Class(%s)',[MapClassName,MapAncestorName]);
  389. DoCreateFieldMapDeclaration(Strings,ObjectClassName,MapClassName,MapAncestorName);
  390. AddLn(Strings,'end;');
  391. Finally
  392. DecIndent;
  393. end;
  394. end;
  395. procedure TDDBaseFieldMapCodeGenerator.CreateFieldMapImplementation(
  396. Strings: TStrings; const ObjectClassName, MapClassName: String);
  397. Var
  398. S : String;
  399. begin
  400. AddLn(Strings,' { %s }',[MapClassName]);
  401. AddLn(Strings);
  402. S:=Format('Procedure %s.InitFields;',[MapClassName]);
  403. BeginMethod(Strings,S);
  404. Try
  405. WriteMapInitFields(Strings,ObjectClassName,MapClassName);
  406. Finally
  407. EndMethod(Strings,S);
  408. end;
  409. if fmoOverrideTransformString in FieldMapOpts.FieldMapOptions then
  410. AddTransFormOverrideImplementations(Strings,MapClassName);
  411. if fmoLoadObject in FieldMapOpts.FieldMapOptions then
  412. begin
  413. WriteFillMethod(Strings, ObjectClassName, MapClassName);
  414. S:=Format('Procedure %s.LoadObject(aObject: TObject);',[MapClassName]);
  415. BeginMethod(Strings,S);
  416. Try
  417. Addln(Strings,'begin');
  418. IncIndent;
  419. AddLn(Strings,'Fill(aObject as %s);',[ObjectClassName]);
  420. DecIndent;
  421. finally
  422. EndMethod(Strings,S);
  423. end;
  424. end;
  425. end;
  426. procedure TDDBaseFieldMapCodeGenerator.CreateParamMapImplementation(
  427. Strings: TStrings; const ObjectClassName, MapClassName: String);
  428. Var
  429. S : String;
  430. begin
  431. AddLn(Strings,' { %s }',[MapClassName]);
  432. AddLn(Strings);
  433. S:=Format('Procedure %s.InitParams;',[MapClassName]);
  434. BeginMethod(Strings,S);
  435. Try
  436. WriteParamMapInitParams(Strings,ObjectClassName,MapClassName);
  437. Finally
  438. EndMethod(Strings,S);
  439. end;
  440. if fmoOverrideTransformString in FieldMapOpts.FieldMapOptions then
  441. AddTransFormOverrideImplementations(Strings,MapClassName);
  442. if fmoLoadObject in FieldMapOpts.FieldMapOptions then
  443. begin
  444. WriteSaveMethod(Strings, ObjectClassName, MapClassName);
  445. S:=Format('Procedure %s.SaveObject(aObject: TObject);',[MapClassName]);
  446. BeginMethod(Strings,S);
  447. Try
  448. Addln(Strings,'begin');
  449. IncIndent;
  450. AddLn(Strings,'Fill(aObject as %s);',[ObjectClassName]);
  451. DecIndent;
  452. finally
  453. EndMethod(Strings,S);
  454. end;
  455. end;
  456. end;
  457. class function TDDBaseFieldMapCodeGenerator.NeedsFieldDefs: Boolean;
  458. begin
  459. Result:=True;
  460. end;
  461. procedure TDDBaseFieldMapCodeGenerator.WriteFillMethod(Strings: TStrings; const ObjectClassName, MapClassName: String);
  462. Const
  463. SAddLoadCode = '// Add code to load property %s (of type %s) from field %s';
  464. SupportedPropTypes = [ptBoolean, // Boolean
  465. ptShortString, ptAnsiString, ptUtf8String, // Ansistring
  466. ptWord,ptByte,ptLongint,ptCardinal,ptSmallInt,ptShortInt, // Integer
  467. ptCurrency, // Currency
  468. ptDateTime // DateTime
  469. ];
  470. Var
  471. S,Fmt : String;
  472. F : TFieldPropDef;
  473. I : Integer;
  474. begin
  475. S:=Format('Procedure %s.Fill(aObject: %s);',[MapClassName,ObjectClassName]);
  476. BeginMethod(Strings,S);
  477. Try
  478. Addln(Strings,'begin');
  479. IncIndent;
  480. Fmt:='%s:=GetFromField(Self.F%s,%s);';
  481. Addln(Strings,'With aObject do');
  482. IncIndent;
  483. Addln(Strings,'begin');
  484. For I:=0 to Fields.Count-1 Do
  485. begin
  486. F:=Fields[i];
  487. If F.PropertyType in SupportedPropTypes then
  488. AddLn(Strings,Fmt,[F.PropertyName,F.PropertyName,F.PropertyName])
  489. else if F.PropertyType in [ptWideString, ptUnicodeString] then
  490. begin
  491. AddLn(Strings,'If Assigned(Self.F%s) then',[F.PropertyName]);
  492. incIndent;
  493. AddLn(Strings,'%s:=F%s.AsUnicodeString;',[F.PropertyName,F.PropertyName]);
  494. DecIndent;
  495. end
  496. else if F.PropertyType in [ptSingle,ptDouble,ptExtended,ptComp] then
  497. begin
  498. AddLn(Strings,'If Assigned(Self.F%s) then',[F.PropertyName]);
  499. incIndent;
  500. AddLn(Strings,'%s:=Self.F%s.AsFloat;',[F.PropertyName,F.PropertyName]);
  501. DecIndent;
  502. end
  503. else if F.PropertyType in [ptInt64,ptQWord] then
  504. begin
  505. AddLn(Strings,'If Assigned(Self.F%s) then',[F.PropertyName]);
  506. incIndent;
  507. AddLn(Strings,'%s:=Self.F%s.AsLargeInt;',[F.PropertyName,F.PropertyName]);
  508. DecIndent;
  509. end
  510. else
  511. AddLn(Strings,SAddLoadCode,[F.PropertyName,GetEnumName(TypeInfo(TPropType),Ord(F.PropertyType)), F.FieldName]);
  512. end;
  513. Addln(Strings,'end;');
  514. DecIndent;
  515. Finally
  516. DecIndent;
  517. EndMethod(Strings,S);
  518. end;
  519. end;
  520. procedure TDDBaseFieldMapCodeGenerator.WriteSaveMethod(Strings: TStrings; const ObjectClassName, MapClassName: String);
  521. Const
  522. SAddLoadCode = '// Add code to save property %s (of type %s) to field %s';
  523. SupportedPropTypes = [ptBoolean, // Boolean
  524. ptShortString, ptAnsiString, ptUtf8String, // Ansistring
  525. ptWord,ptByte,ptLongint,ptCardinal,ptSmallInt,ptShortInt, // Integer
  526. ptCurrency, // Currency
  527. ptDateTime // DateTime
  528. ];
  529. Var
  530. S,Fmt : String;
  531. F : TFieldPropDef;
  532. I : Integer;
  533. begin
  534. S:=Format('Procedure %s.Save(aObject: %s);',[MapClassName,ObjectClassName]);
  535. BeginMethod(Strings,S);
  536. Try
  537. Addln(Strings,'begin');
  538. IncIndent;
  539. Fmt:='SetParam(Self.F%s,%s);';
  540. Addln(Strings,'With aObject do');
  541. IncIndent;
  542. Addln(Strings,'begin');
  543. For I:=0 to Fields.Count-1 Do
  544. begin
  545. F:=Fields[i];
  546. If F.PropertyType in SupportedPropTypes then
  547. AddLn(Strings,Fmt,[F.PropertyName,F.PropertyName,F.PropertyName])
  548. else if F.PropertyType in [ptWideString, ptUnicodeString] then
  549. begin
  550. AddLn(Strings,'If Assigned(Self.F%s) then',[F.PropertyName]);
  551. incIndent;
  552. AddLn(Strings,'%s:=F%s.AsUnicodeString;',[F.PropertyName,F.PropertyName]);
  553. DecIndent;
  554. end
  555. else if F.PropertyType in [ptSingle,ptDouble,ptExtended,ptComp] then
  556. begin
  557. AddLn(Strings,'If Assigned(Self.F%s) then',[F.PropertyName]);
  558. incIndent;
  559. AddLn(Strings,'%s:=Self.F%s.AsFloat;',[F.PropertyName,F.PropertyName]);
  560. DecIndent;
  561. end
  562. else if F.PropertyType in [ptInt64,ptQWord] then
  563. begin
  564. AddLn(Strings,'If Assigned(Self.F%s) then',[F.PropertyName]);
  565. incIndent;
  566. AddLn(Strings,'%s:=Self.F%s.AsLargeInt;',[F.PropertyName,F.PropertyName]);
  567. DecIndent;
  568. end
  569. else
  570. AddLn(Strings,SAddLoadCode,[F.PropertyName,GetEnumName(TypeInfo(TPropType),Ord(F.PropertyType)), F.FieldName]);
  571. end;
  572. Addln(Strings,'end;');
  573. DecIndent;
  574. Finally
  575. DecIndent;
  576. EndMethod(Strings,S);
  577. end;
  578. end;
  579. procedure TDDBaseFieldMapCodeGenerator.WriteMapInitFields(Strings: TStrings;
  580. const ObjectClassName, MapClassName: String);
  581. Const
  582. Finders : Array[Boolean] of string = ('FindField','FieldByName');
  583. Var
  584. I: Integer;
  585. F : TFieldPropDef;
  586. Fmt : String;
  587. begin
  588. AddLn(Strings,'begin');
  589. IncIndent;
  590. try
  591. Fmt:='F%s:='+Finders[fmoRequireFields in FieldMapOpts.FieldMapOptions]+'(%s);';
  592. For I:=0 to Fields.Count-1 Do
  593. begin
  594. F:=Fields[i];
  595. If F.Enabled then
  596. AddLn(Strings,Fmt,[F.PropertyName,CreateString(F.FieldName)]);
  597. end;
  598. Finally
  599. DecIndent;
  600. end;
  601. end;
  602. procedure TDDBaseFieldMapCodeGenerator.WriteParamMapInitParams(Strings: TStrings;
  603. const ObjectClassName, MapClassName: String);
  604. Const
  605. Finders : Array[Boolean] of string = ('FindParam','ParamByName');
  606. Var
  607. I: Integer;
  608. F : TFieldPropDef;
  609. Fmt : String;
  610. begin
  611. AddLn(Strings,'begin');
  612. IncIndent;
  613. try
  614. Fmt:='F%s:='+Finders[fmoRequireFields in FieldMapOpts.FieldMapOptions]+'(%s);';
  615. For I:=0 to Fields.Count-1 Do
  616. begin
  617. F:=Fields[i];
  618. If F.Enabled then
  619. AddLn(Strings,Fmt,[F.PropertyName,CreateString(F.FieldName)]);
  620. end;
  621. Finally
  622. DecIndent;
  623. end;
  624. end;
  625. { TGenFieldMapOptions }
  626. function TGenFieldMapOptions.GetParamMapAncestorName: String;
  627. begin
  628. Result:=FParamMapAncestorClassName;
  629. if Result='' then
  630. Result:='TParamMap';
  631. end;
  632. function TGenFieldMapOptions.GetParamMapName: String;
  633. begin
  634. Result:=FParamMapClassName;
  635. if Result='' then
  636. Result:=ObjectClassName+'ParamMap';
  637. end;
  638. procedure TGenFieldMapOptions.SetParamMapAncestorName(const aValue: String);
  639. begin
  640. FParamMapAncestorClassName:=aValue;
  641. end;
  642. procedure TGenFieldMapOptions.SetParamMapClassName(const aValue: String);
  643. begin
  644. FParamMapClassName:=aValue;
  645. end;
  646. function TGenFieldMapOptions.GetMapAncestorName: String;
  647. begin
  648. Result:=FMapAncestorClassName;
  649. if Result='' then
  650. Result:='TFieldMap';
  651. end;
  652. function TGenFieldMapOptions.GetMapName: String;
  653. begin
  654. Result:=FMapClassName;
  655. if Result='' then
  656. Result:=ObjectClassName+'Map';
  657. end;
  658. procedure TGenFieldMapOptions.SetMapAncestorName(const aValue: String);
  659. begin
  660. FMapAncestorClassName:=aValue;
  661. end;
  662. procedure TGenFieldMapOptions.SetMapClassName(const aValue: String);
  663. begin
  664. FMapClassName:=aValue;
  665. end;
  666. constructor TGenFieldMapOptions.Create;
  667. begin
  668. inherited Create;
  669. AncestorClass:='TObject';
  670. ObjectClassName:='TMyObject';
  671. // The rest is auto generated if empty
  672. end;
  673. procedure TGenFieldMapOptions.Assign(aSource: TPersistent);
  674. Var
  675. O : TGenFieldMapOptions;
  676. begin
  677. if ASource is TGenFieldMapOptions then
  678. begin
  679. O:=ASource as TGenFieldMapOptions;
  680. FMapClassName:=O.FMapClassName;
  681. FMapAncestorClassName:=O.FMapAncestorClassName;
  682. FParamMapClassName:=O.FParamMapClassName;
  683. FParamMapAncestorClassName:=O.FParamMapAncestorClassName;
  684. FieldMapOptions:=O.FieldMapOptions;
  685. FListParent:=O.ListParent;
  686. end;
  687. inherited Assign(ASource);
  688. end;
  689. Initialization
  690. RegisterCodeGenerator('FieldMap','Object and TFieldMap descendent.',TDDDBFieldMapCodeGenerator);
  691. Finalization
  692. UnRegisterCodeGenerator(TDDDBFieldMapCodeGenerator);
  693. end.