From 56573899d3218a2858cfce76ea780a9e945907b0 Mon Sep 17 00:00:00 2001 From: Daniele Teti Date: Tue, 29 Aug 2023 23:51:08 +0200 Subject: [PATCH] TMVCResponseBuilder and IMVCResponseBuilder (WIP) --- .gitignore | 1 + .../funcion_actions_showcase/ControllerU.pas | 32 +++++ sources/MVCFramework.pas | 111 ++++++++++++++++++ 3 files changed, 144 insertions(+) diff --git a/.gitignore b/.gitignore index d94145c8..1bd99124 100644 --- a/.gitignore +++ b/.gitignore @@ -145,3 +145,4 @@ samples/WineCellarSample/winecellarclient_mobile/Android/Debug/styles-v21.xml samples/WineCellarSample/winecellarclient_mobile/Android/Debug/WineCellarMobileClient.classes/classes.dex samples/apachemodule/Apache24/logs/httpd.pid samples/session_file_based/Win32/DEBUG/sessions/ +unittests/general/UnitTestReports/ diff --git a/samples/funcion_actions_showcase/ControllerU.pas b/samples/funcion_actions_showcase/ControllerU.pas index 8fb632d3..6ec604f8 100644 --- a/samples/funcion_actions_showcase/ControllerU.pas +++ b/samples/funcion_actions_showcase/ControllerU.pas @@ -70,6 +70,13 @@ type function GetMVCResponseWithObjectDictionary: IMVCResponse; [MVCPath('/mvcresponse/error')] function GetMVCErrorResponse: IMVCResponse; + + { using MVCResponseBuilder } + [MVCPath('/mvcresponse/message/builder')] + function GetMVCResponseSimpleBuilder: IMVCResponse; + [MVCPath('/mvcresponse/data/builder')] + function GetMVCResponseWithDataBuilder: IMVCResponse; + end; implementation @@ -140,11 +147,36 @@ begin Result := MVCResponse(HTTP_STATUS.OK, 'My Message', 'My Reason String'); end; +function TMyController.GetMVCResponseSimpleBuilder: IMVCResponse; +begin + Result := MVCResponseBuilder + .StatusCode(HTTP_STATUS.OK) + .Message('My Message') + .Reason('My Reason String') + .Build; + + //Equivalent to the following + // + //Result := MVCResponse(HTTP_STATUS.OK, 'My Message', 'My Reason String'); +end; + function TMyController.GetMVCResponseWithData: IMVCResponse; begin Result := MVCResponse(HTTP_STATUS.OK, TPerson.Create('Daniele','Teti', 99)); end; +function TMyController.GetMVCResponseWithDataBuilder: IMVCResponse; +begin + Result := MVCResponseBuilder + .StatusCode(HTTP_STATUS.OK) + .Data(TPerson.Create('Daniele','Teti', 99)) + .Build; + + //Equivalent to the following + // + //Result := MVCResponse(HTTP_STATUS.OK, TPerson.Create('Daniele','Teti', 99)); +end; + function TMyController.GetMVCResponseWithObjectDictionary: IMVCResponse; begin Result := MVCResponse( diff --git a/sources/MVCFramework.pas b/sources/MVCFramework.pas index aa6556ed..edfd5304 100644 --- a/sources/MVCFramework.pas +++ b/sources/MVCFramework.pas @@ -1154,6 +1154,19 @@ function CreateResponse(const StatusCode: UInt16; const ReasonString: string; function MVCResponse(AStatusCode: Integer; AMessage: string = ''; AReasonString: string = ''): IMVCResponse; overload; function MVCResponse(AStatusCode: Integer; AData: TObject; AReasonString: string = ''): IMVCResponse; overload; function MVCResponse(AStatusCode: Integer; AObjectDictionary: IMVCObjectDictionary; AReasonString: string = ''): IMVCResponse; overload; + +type + IMVCResponseBuilder = interface + ['{10210D72-AFAE-4919-936D-EB08AA16C01C}'] + function StatusCode(const StatusCode: Integer): IMVCResponseBuilder; + function Message(const Message: String): IMVCResponseBuilder; + function Data(const Data: TObject): IMVCResponseBuilder; + function Reason(const Reason: String): IMVCResponseBuilder; + function ObjectDict(const ObjDictionary: IMVCObjectDictionary): IMVCResponseBuilder; + function Build: IMVCResponse; + end; + +function MVCResponseBuilder: IMVCResponseBuilder; // end - std responses implementation @@ -1175,6 +1188,29 @@ var gHostingFramework: TMVCHostingFrameworkType = hftUnknown; +type + TMVCResponseBuilder = class sealed(TInterfacedObject, IMVCResponseBuilder) + private + fBuilt: Boolean; + protected + fStatusCode: Integer; + fMessage: String; + fData: TObject; + fReason: String; + fObjectDict: IMVCObjectDictionary; + + function StatusCode(const StatusCode: Integer): IMVCResponseBuilder; + function Message(const Message: String): IMVCResponseBuilder; + function Data(const Data: TObject): IMVCResponseBuilder; + function Reason(const Reason: String): IMVCResponseBuilder; + function ObjectDict(const ObjDictionary: IMVCObjectDictionary): IMVCResponseBuilder; + function Build: IMVCResponse; + public + constructor Create; virtual; + destructor Destroy; override; + end; + + function IsShuttingDown: Boolean; begin Result := gIsShuttingDown; @@ -4589,9 +4625,84 @@ begin Result := TMVCResponse.Create(AStatusCode, AObjectDictionary, AReasonString); end; +function MVCResponseBuilder: IMVCResponseBuilder; +begin + Result := TMVCResponseBuilder.Create; +end; + // end - std responses +{ TMVCResponseBuilder } + +function TMVCResponseBuilder.Build: IMVCResponse; +begin + if (fData = nil) and (fObjectDict = nil) then + begin + Result := MVCResponse(fStatusCode, fMessage, fReason); + end + else + begin + if fData = nil then + begin + Result := MVCResponse(fStatusCode, fObjectDict, fReason); + end + else + begin + Result := MVCResponse(fStatusCode, fData, fReason); + end; + end; + fBuilt := True; +end; + +constructor TMVCResponseBuilder.Create; +begin + inherited; + fBuilt := False; +end; + +function TMVCResponseBuilder.Data(const Data: TObject): IMVCResponseBuilder; +begin + fData := Data; + Result := Self; +end; + +destructor TMVCResponseBuilder.Destroy; +begin + if not fBuilt then + begin + FreeAndNil(fData); + end; + inherited; +end; + +function TMVCResponseBuilder.Message( + const Message: String): IMVCResponseBuilder; +begin + fMessage := Message; + Result := Self; +end; + +function TMVCResponseBuilder.ObjectDict( + const ObjDictionary: IMVCObjectDictionary): IMVCResponseBuilder; +begin + fObjectDict := ObjDictionary; + Result := Self; +end; + +function TMVCResponseBuilder.Reason(const Reason: String): IMVCResponseBuilder; +begin + fReason := Reason; + Result := Self; +end; + +function TMVCResponseBuilder.StatusCode( + const StatusCode: Integer): IMVCResponseBuilder; +begin + fStatusCode := StatusCode; + Result := Self; +end; + initialization // https://quality.embarcadero.com/browse/RSP-38281