summaryrefslogtreecommitdiff
path: root/packages/fcl-mustache/src/fpdbmustache.pp
diff options
context:
space:
mode:
Diffstat (limited to 'packages/fcl-mustache/src/fpdbmustache.pp')
-rw-r--r--packages/fcl-mustache/src/fpdbmustache.pp268
1 files changed, 268 insertions, 0 deletions
diff --git a/packages/fcl-mustache/src/fpdbmustache.pp b/packages/fcl-mustache/src/fpdbmustache.pp
new file mode 100644
index 0000000000..0f7d6d72d9
--- /dev/null
+++ b/packages/fcl-mustache/src/fpdbmustache.pp
@@ -0,0 +1,268 @@
+{
+ This file is part of the Free Pascal Run time library.
+ Copyright (c) 2021 by Michael Van Canneyt (michael@freepascal.org)
+
+ This file contains a Mustache DB context, getting data from a dataset
+
+ See the File COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+unit fpdbmustache;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, db, fpMustache;
+
+Type
+
+ { TDatasetCollectionItem }
+
+ TDatasetCollectionItem = Class(TCollectionItem)
+ private
+ FDataset: TDataSet;
+ FSection: String;
+ Public
+ Property Dataset : TDataSet Read FDataset Write FDataset;
+ Property SectionName : String Read FSection Write FSection;
+ end;
+
+ TDatasetCollection = Class(TCollection)
+ private
+ function GetDS(aIndex : Integer): TDatasetCollectionItem;
+ Public
+ Function IndexOfDataset(aDataset : TDataset) : Integer;
+ Function IndexOfSection(aSection : String) : Integer;
+ Property Datasets[aIndex : Integer] : TDatasetCollectionItem Read GetDS; default;
+ end;
+
+ { TMustacheDBContext }
+
+ TMustacheDBContext = Class(TMustacheContext)
+ Private
+ Type
+ TPair = Record
+ atStart : Boolean;
+ Value : TDataset;
+ end;
+ Private
+ FStack : Array of TPair;
+ FCount : Integer;
+ FStaticValues: TStrings;
+ FDatasets : TDatasetCollection;
+ Function FindField(Const aName : TMustacheString) : TField;
+ function GetDataset(aIndex : Integer): TDatasetCollectionItem;
+ function GetDatasetCount: INteger;
+ procedure SetStaticValues(AValue: TStrings);
+ Public
+ Constructor Create(aCallback : TGetTextValueEvent); override;
+ Destructor destroy; override;
+ Procedure Clear;
+ Function MoveNextSectionItem(Const aName : TMustacheString) : Boolean; override;
+ Function PushSection(Const aName : TMustacheString) : TMustacheSectionType; override;
+ Procedure PopSection(Const aName : TMustacheString); override;
+ Function GetTextValue(Const aName : TMustacheString) : TMustacheString; override;
+ Procedure AddDataset(aDataset : TDataset; aSectionName : String = '');
+ Procedure RemoveDataset(aDataset : TDataset);
+ Property StaticValues : TStrings Read FStaticValues Write SetStaticValues;
+ Property Datasets[aIndex : Integer] : TDatasetCollectionItem Read GetDataset;
+ Property DatasetCount : INteger Read GetDatasetCount;
+ end;
+
+implementation
+
+uses StrUtils;
+
+Resourcestring
+ SErrPopSectionNoPush = 'PopSection %s without push';
+ SErrDatasetNameEmpty = 'Dataset name and section cannot both be empty';
+ SErrDatasetEmpty = 'Dataset is Nil';
+ SErrDuplicateDataSetName = 'Duplicate dataset name: %s';
+
+{ TMustacheDBContext }
+
+function TMustacheDBContext.FindField(const aName: TMustacheString): TField;
+
+Var
+ aCount : Integer;
+
+begin
+ Result:=Nil;
+ aCount:=FCount-1;
+ While (Result=Nil) and (aCount>=0) do
+ begin
+ Result:=FStack[aCount].Value.FieldByName(aName);
+ Dec(aCount);
+ end;
+end;
+
+function TMustacheDBContext.GetDataset(aIndex : Integer
+ ): TDatasetCollectionItem;
+begin
+ Result:=FDatasets[aIndex];
+end;
+
+function TMustacheDBContext.GetDatasetCount: INteger;
+begin
+ Result:=FDatasets.Count;
+end;
+
+procedure TMustacheDBContext.SetStaticValues(AValue: TStrings);
+begin
+ if FStaticValues=AValue then Exit;
+ FStaticValues.Assign(AValue);
+end;
+
+constructor TMustacheDBContext.Create(aCallback: TGetTextValueEvent);
+begin
+ inherited Create(aCallback);
+ FDatasets:=TDatasetCollection.Create(TDatasetCollectionItem);
+ FStaticValues:=TStringList.Create;
+ SetLength(FStack,JSONListGrowCount);
+ FCount:=0;
+end;
+
+destructor TMustacheDBContext.destroy;
+begin
+ FreeAndNil(FStaticValues);
+ FreeAndNil(FDatasets);
+ inherited destroy;
+end;
+
+procedure TMustacheDBContext.Clear;
+begin
+ FStaticValues.Clear;
+ FDatasets.Clear;
+end;
+
+function TMustacheDBContext.MoveNextSectionItem(const aName: TMustacheString
+ ): Boolean;
+begin
+ if FStack[FCount-1].atStart then
+ FStack[FCount-1].atStart:=False
+ else
+ FStack[FCount-1].Value.Next;
+ Result:=Not FStack[FCount-1].Value.EOF;
+end;
+
+function TMustacheDBContext.PushSection(const aName: TMustacheString
+ ): TMustacheSectionType;
+
+Var
+ aDS : TDataset;
+ Idx : Integer;
+begin
+ Result:=mstNone;
+ Idx:=FDatasets.IndexOfSection(aName);
+ if Idx=-1 then
+ Exit;
+ aDS:=FDatasets[Idx].Dataset;
+ if aDS.IsEmpty then
+ exit;
+ if FCount=Length(FStack) then
+ SetLength(FStack,FCount+JSONListGrowCount);
+ FStack[FCount].Value:=aDS;
+ FStack[FCount].atStart:=True;
+ Inc(FCount,1);
+ Result:=mstList;
+end;
+
+procedure TMustacheDBContext.PopSection(const aName: TMustacheString);
+begin
+ if FCount<1 then
+ Raise EMustache.CreateFmt(SErrPopSectionNoPush,[aName]);
+ Dec(FCount,1);
+end;
+
+function TMustacheDBContext.GetTextValue(const aName: TMustacheString
+ ): TMustacheString;
+
+Var
+ F : TField;
+ idx : Integer;
+
+begin
+ F:=Nil;
+ if Pos('.',aName)=0 then
+ F:=FindField(aName)
+ else if WordCount(aName,['.'])=2 then
+ begin
+ Idx:=FDatasets.IndexOfSection(ExtractWord(1,aName,['.']));
+ if (Idx<>-1) then
+ F:=FDatasets[Idx].Dataset.FindField(ExtractWord(2,aName,['.']));
+ end;
+ If Assigned(F) then
+ Result:=F.AsString
+ else
+ begin
+ Idx:=FStaticValues.IndexOfName(aName);
+ if Idx<>-1 then
+ Result:=FStaticValues.ValueFromIndex[Idx]
+ else
+ Result:=Inherited GetTextValue(aName);
+ end;
+end;
+
+procedure TMustacheDBContext.AddDataset(aDataset: TDataset; aSectionName: String);
+
+Var
+ DCI : TDatasetCollectionItem;
+ aName : String;
+
+begin
+ aName:=aSectionName;
+ if aName='' then
+ aName:=aDataset.Name;
+ if aName='' then
+ raise EMustache.Create(SErrDatasetNameEmpty);
+ if aDataset=Nil then
+ raise EMustache.Create(SErrDatasetEmpty);
+ if FDatasets.IndexOfSection(aName)<>-1 then
+ raise EMustache.CreateFmt(SErrDuplicateDataSetName, [aName]);
+ DCI:=FDatasets.Add as TDatasetCollectionItem;
+ DCI.Dataset:=aDataset;
+ DCI.SectionName:=aName;
+end;
+
+procedure TMustacheDBContext.RemoveDataset(aDataset: TDataset);
+
+Var
+ Idx : Integer;
+
+begin
+ Idx:=FDatasets.IndexOfDataset(aDataset);
+ if Idx<>-1 then
+ FDatasets.Delete(Idx);
+end;
+
+{ TDatasetCollection }
+
+function TDatasetCollection.GetDS(aIndex : Integer): TDatasetCollectionItem;
+begin
+ Result:=Items[aIndex] as TDatasetCollectionItem;
+end;
+
+function TDatasetCollection.IndexOfDataset(aDataset: TDataset): Integer;
+begin
+ Result:=Count-1;
+ While (Result>=0) and (GetDS(Result).Dataset<>ADataset) do
+ Dec(Result);
+end;
+
+function TDatasetCollection.IndexOfSection(aSection: String): Integer;
+begin
+ Result:=Count-1;
+ While (Result>=0) and not SameText(GetDS(Result).SectionName,ASection) do
+ Dec(Result);
+end;
+
+end.
+