123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- unit fpcgfieldmap;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, fpddcodegen;
- Type
- { TGenFieldMapOptions }
- TFieldMapOption = (fmoPublicFields,fmoRequireFields,fmoLoadObject);
- TFieldMapOptions = Set of TFieldMapOption;
- TGenFieldMapOptions = Class(TClassCodeGeneratorOptions)
- Private
- FOptions: TFieldMapOptions;
- FMapClassName : String;
- FMapAncestorClassName : String;
- Protected
- function GetMapAncestorName: String; virtual;
- function GetMapName: String; virtual;
- procedure SetMapAncestorName(const AValue: String); virtual;
- procedure SetMapClassName(const AValue: String); virtual;
- Public
- Constructor Create; override;
- Procedure Assign(ASource: TPersistent); override;
- Property MapAncestorName : String Read GetMapAncestorName Write SetMapAncestorName;
- Property MapClassName : String Read GetMapName Write SetMapClassName;
- Property AncestorClass;
- Published
- Property FieldMapOptions : TFieldMapOptions Read FOptions Write FOptions;
- end;
- { TDDDBFieldMapCodeGenerator }
- { TDDBaseFieldMapCodeGenerator }
- TDDBaseFieldMapCodeGenerator = Class(TDDClassCodeGenerator)
- private
- function GetOpt: TGenFieldMapOptions;
- Protected
- // Overrides;
- Function GetInterfaceUsesClause : string; override;
- Function CreateOptions : TCodeGeneratorOptions; override;
- // New methods
- procedure WriteFillMethod(Strings: TStrings; const ObjectClassName, MapClassName: String); virtual;
- procedure DoCreateFieldMapDeclaration(Strings: TStrings; const ObjectClassName,MapClassName, MapAncestorName: String); virtual;
- procedure WriteMapInitFields(Strings: TStrings; const ObjectClassName, MapClassName: String); virtual;
- procedure CreateFieldMapImplementation(Strings: TStrings; const ObjectClassName, MapClassName: String);
- Property FieldMapOpts : TGenFieldMapOptions Read Getopt;
- Public
- Class function NeedsFieldDefs: Boolean; override;
- procedure CreateFieldMapDeclaration(Strings: TStrings; const ObjectClassName,MapClassName, MapAncestorName: String);
- end;
- { TGenFieldMapCodeGenOptions }
- TGenFieldMapCodeGenOptions = class(TGenFieldMapOptions)
- Public
- constructor create; override;
- Published
- Property AncestorClass;
- Property MapClassName;
- Property MapAncestorName;
- end;
- TDDDBFieldMapCodeGenerator = Class(TDDBaseFieldMapCodeGenerator)
- Protected
- Function CreateOptions : TCodeGeneratorOptions; override;
- Procedure DoGenerateInterface(Strings: TStrings); override;
- Procedure DoGenerateImplementation(Strings: TStrings); override;
- Public
- Property FieldMapOpts;
- end;
- implementation
- uses typinfo;
- { TGenFieldMapCodeGenOptions }
- constructor TGenFieldMapCodeGenOptions.create;
- begin
- inherited create;
- FieldMapOptions:=[fmoLoadObject]
- end;
- { TDDDBFieldMapCodeGenerator }
- function TDDBaseFieldMapCodeGenerator.GetOpt: TGenFieldMapOptions;
- begin
- Result:=CodeOptions as TGenFieldMapOptions;
- end;
- function TDDBaseFieldMapCodeGenerator.GetInterfaceUsesClause: string;
- begin
- Result:=inherited GetInterfaceUsesClause;
- If (Result<>'') then
- Result:=Result+', db, fieldmap';
- end;
- procedure TDDDBFieldMapCodeGenerator.DoGenerateInterface(Strings: TStrings);
- begin
- inherited DoGenerateInterface(Strings);
- AddLn(Strings,'Type');
- CreatefieldMapDeclaration(Strings,GetOpt.ObjectClassName,GetOpt.MapClassName,GetOpt.MapAncestorName);
- end;
- procedure TDDDBFieldMapCodeGenerator.DoGenerateImplementation(Strings: TStrings
- );
- begin
- inherited DoGenerateImplementation(Strings);
- With FieldMapOpts do
- CreateFieldMapImplementation(Strings,ObjectClassName,MapClassName);
- end;
- Function TDDDBFieldMapCodeGenerator.CreateOptions : TCodeGeneratorOptions;
- begin
- Result:=TGenFieldMapCodeGenOptions.Create
- end;
- function TDDBaseFieldMapCodeGenerator.CreateOptions: TCodeGeneratorOptions;
- begin
- Result:=TGenFieldMapOptions.Create;
- end;
- procedure TDDBaseFieldMapCodeGenerator.DoCreateFieldMapDeclaration(
- Strings: TStrings; const ObjectClassName, MapClassName,
- MapAncestorName: String);
- Var
- I : Integer;
- F : TFieldPropDef;
- begin
- AddLn(Strings,'Private');
- IncIndent;
- Try
- For I:=0 to Fields.Count-1 do
- begin
- F:=Fields[I];
- If F.Enabled then
- AddLn(Strings,'F%s : TField;',[F.PropertyName]);
- end;
- Finally
- DecIndent;
- end;
- AddLn(Strings,'Public');
- IncIndent;
- Try
- AddLn(Strings,'Procedure InitFields; Override;');
- if fmoLoadObject in FieldMapOpts.FieldMapOptions then
- begin
- AddLn(Strings,'Procedure Fill(aObject: %s); virtual;',[ObjectClassName]);
- AddLn(Strings,'Procedure LoadObject(aObject: TObject); override;');
- end;
- if fmoPublicFields in FieldMapOpts.FieldMapOptions then
- For I:=0 to Fields.Count-1 do
- begin
- F:=Fields[I];
- If F.Enabled then
- AddLn(Strings,'Property %s : TField read F%s;',[F.PropertyName,F.FieldName]);
- end;
- Finally
- DecIndent;
- end;
- end;
- procedure TDDBaseFieldMapCodeGenerator.CreateFieldMapDeclaration(Strings: TStrings; const ObjectClassName, MapClassName, MapAncestorName: String);
- begin
- Addln(Strings);
- IncIndent;
- try
- Addln(Strings,'{ %s }',[MapClassName]);
- Addln(Strings);
- Addln(Strings,'%s = Class(%s)',[MapClassName,MapAncestorName]);
- DoCreateFieldMapDeclaration(Strings,ObjectClassName,MapClassName,MapAncestorName);
- AddLn(Strings,'end;');
- Finally
- DecIndent;
- end;
- end;
- procedure TDDBaseFieldMapCodeGenerator.CreateFieldMapImplementation(
- Strings: TStrings; const ObjectClassName, MapClassName: String);
- Var
- S : String;
- begin
- AddLn(Strings,' { %s }',[MapClassName]);
- AddLn(Strings);
- S:=Format('Procedure %s.InitFields;',[MapClassName]);
- BeginMethod(Strings,S);
- Try
- WriteMapInitFields(Strings,ObjectClassName,MapClassName);
- Finally
- EndMethod(Strings,S);
- end;
- if fmoLoadObject in FieldMapOpts.FieldMapOptions then
- begin
- WriteFillMethod(Strings, ObjectClassName, MapClassName);
- S:=Format('Procedure %s.LoadObject(aObject: TObject);',[MapClassName]);
- BeginMethod(Strings,S);
- Try
- Addln(Strings,'begin');
- IncIndent;
- AddLn(Strings,'Fill(aObject as %s);',[ObjectClassName]);
- DecIndent;
- finally
- EndMethod(Strings,S);
- end;
- end;
- end;
- class function TDDBaseFieldMapCodeGenerator.NeedsFieldDefs: Boolean;
- begin
- Result:=True;
- end;
- procedure TDDBaseFieldMapCodeGenerator.WriteFillMethod(Strings: TStrings; const ObjectClassName, MapClassName: String);
- Const
- SAddLoadCode = '// Add code to load property %s (of type %s) from field %s';
- SupportedPropTypes = [ptBoolean, // Boolean
- ptShortString, ptAnsiString, ptUtf8String, // Ansistring
- ptWord,ptByte,ptLongint,ptCardinal,ptSmallInt,ptShortInt, // Integer
- ptCurrency, // Currency
- ptDateTime // DateTime
- ];
- Var
- S,Fmt : String;
- F : TFieldPropDef;
- I : Integer;
- begin
- S:=Format('Procedure %s.Fill(aObject: %s);',[MapClassName,ObjectClassName]);
- BeginMethod(Strings,S);
- Try
- Addln(Strings,'begin');
- IncIndent;
- Fmt:='%s:=GetFromField(Self.F%s,%s);';
- Addln(Strings,'With aObject do');
- IncIndent;
- Addln(Strings,'begin');
- For I:=0 to Fields.Count-1 Do
- begin
- F:=Fields[i];
- If F.PropertyType in SupportedPropTypes then
- AddLn(Strings,Fmt,[F.PropertyName,F.PropertyName,F.PropertyName])
- else if F.PropertyType in [ptWideString, ptUnicodeString] then
- begin
- AddLn(Strings,'If Assigned(Self.F%s) then',[F.PropertyName]);
- incIndent;
- AddLn(Strings,'%s:=F%s.AsUnicodeString;',[F.PropertyName,F.PropertyName]);
- DecIndent;
- end
- else if F.PropertyType in [ptSingle,ptDouble,ptExtended,ptComp] then
- begin
- AddLn(Strings,'If Assigned(Self.F%s) then',[F.PropertyName]);
- incIndent;
- AddLn(Strings,'%s:=Self.F%s.AsFloat;',[F.PropertyName,F.PropertyName]);
- DecIndent;
- end
- else if F.PropertyType in [ptInt64,ptQWord] then
- begin
- AddLn(Strings,'If Assigned(Self.F%s) then',[F.PropertyName]);
- incIndent;
- AddLn(Strings,'%s:=Self.F%s.AsLargeInt;',[F.PropertyName,F.PropertyName]);
- DecIndent;
- end
- else
- AddLn(Strings,SAddLoadCode,[F.PropertyName,GetEnumName(TypeInfo(TPropType),Ord(F.PropertyType)), F.FieldName]);
- end;
- Addln(Strings,'end;');
- DecIndent;
- Finally
- DecIndent;
- EndMethod(Strings,S);
- end;
- end;
- procedure TDDBaseFieldMapCodeGenerator.WriteMapInitFields(Strings: TStrings;
- const ObjectClassName, MapClassName: String);
- Const
- Finders : Array[Boolean] of string = ('FindField','FieldByName');
- Var
- I: Integer;
- F : TFieldPropDef;
- Fmt : String;
- begin
- AddLn(Strings,'begin');
- IncIndent;
- try
- Fmt:='F%s:='+Finders[fmoRequireFields in FieldMapOpts.FieldMapOptions]+'(%s);';
- For I:=0 to Fields.Count-1 Do
- begin
- F:=Fields[i];
- If F.Enabled then
- AddLn(Strings,Fmt,[F.PropertyName,CreateString(F.FieldName)]);
- end;
- Finally
- DecIndent;
- end;
- end;
- { TGenFieldMapOptions }
- function TGenFieldMapOptions.GetMapAncestorName: String;
- begin
- Result:=FMapAncestorClassName;
- if Result='' then
- Result:='TFieldMap';
- end;
- function TGenFieldMapOptions.GetMapName: String;
- begin
- Result:=FMapClassName;
- if Result='' then
- Result:=ObjectClassName+'Map';
- end;
- procedure TGenFieldMapOptions.SetMapAncestorName(const AValue: String);
- begin
- FMapAncestorClassName:=AValue;
- end;
- procedure TGenFieldMapOptions.SetMapClassName(const AValue: String);
- begin
- FMapClassName:=AValue;
- end;
- constructor TGenFieldMapOptions.Create;
- begin
- inherited Create;
- AncestorClass:='TObject';
- ObjectClassName:='TMyObject';
- MapClassName:='TMyObjectMap';
- MapAncestorName:='TFieldMap';
- end;
- procedure TGenFieldMapOptions.Assign(ASource: TPersistent);
- Var
- O : TGenFieldMapOptions;
- begin
- if ASource is TGenFieldMapOptions then
- begin
- O:=ASource as TGenFieldMapOptions;
- MapClassName:=O.MapClassName;
- MapAncestorName:=O.MapAncestorName;
- FieldMapOptions:=O.FieldMapOptions;
- end;
- inherited Assign(ASource);
- end;
- Initialization
- RegisterCodeGenerator('FieldMap','Object and TFieldMap descendent.',TDDDBFieldMapCodeGenerator);
- Finalization
- UnRegisterCodeGenerator(TDDDBFieldMapCodeGenerator);
- end.
|