2016-06-22 17:49:16 +02:00
// ***************************************************************************
//
// Delphi MVC Framework
//
2020-01-06 16:49:18 +01:00
// Copyright (c) 2010-2020 Daniele Teti and the DMVCFramework Team
2016-06-22 17:49:16 +02:00
//
// https://github.com/danieleteti/delphimvcframework
//
// ***************************************************************************
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// *************************************************************************** }
2015-01-14 11:39:44 +01:00
unit MVCFramework. RESTAdapter;
2017-01-18 21:53:53 +01:00
{$I dmvcframework.inc}
2015-01-14 11:39:44 +01:00
interface
uses
2020-09-02 16:13:29 +02:00
System. Rtti, System. TypInfo, MVCFramework. RESTClient, MVCFramework. Commons,
IdIOHandler, System. Classes, System. SysUtils;
2015-01-14 11:39:44 +01:00
2015-01-17 17:19:09 +01:00
const
URL_SEPARATOR = '/' ;
2015-01-14 11:39:44 +01:00
type
2017-01-18 21:53:53 +01:00
RESTResourceAttribute = class( TCustomAttribute)
2015-01-14 11:39:44 +01:00
private
2020-09-02 16:13:29 +02:00
FURL: string ;
FHTTPMethodType: TMVCHTTPMethodType;
2015-01-14 11:39:44 +01:00
procedure SetURL( const Value: string ) ;
procedure SetHTTPMethodType( const Value: TMVCHTTPMethodType) ;
public
constructor Create( AMVCHTTPMethod: TMVCHTTPMethodType; AURL: string ) ;
2020-09-02 16:13:29 +02:00
property URL: string read FURL write SetURL;
property HTTPMethodType: TMVCHTTPMethodType read FHTTPMethodType
write SetHTTPMethodType;
2015-01-14 11:39:44 +01:00
end ;
BodyAttribute = class( TCustomAttribute)
private
2020-09-02 16:13:29 +02:00
FOwnsObject: boolean ;
procedure SetOwnsObject( const Value: boolean ) ;
2015-01-14 11:39:44 +01:00
public
2020-09-02 16:13:29 +02:00
constructor Create( AOwnsObject: boolean = true ) ;
property OwnsObject: boolean read FOwnsObject write SetOwnsObject;
2015-01-14 11:39:44 +01:00
end ;
ParamAttribute = class( TCustomAttribute)
private
2020-09-02 16:13:29 +02:00
FParamType: string ;
FCustomFormat: string ;
FParamMatch: string ;
2015-01-14 11:39:44 +01:00
procedure SetCustomFormat( const Value: string ) ;
procedure SetParamType( const Value: string ) ;
2015-01-17 17:19:09 +01:00
procedure SetParamMatch( const Value: string ) ;
2015-01-14 11:39:44 +01:00
public
2020-09-02 16:13:29 +02:00
constructor Create( AParamMatch: string ; AParamType: string = '' ;
ACustomFormat: string = '' ) ;
property ParamMatch: string read FParamMatch write SetParamMatch;
property ParamType: string read FParamType write SetParamType;
property CustomFormat: string read FCustomFormat write SetCustomFormat;
2015-01-17 17:19:09 +01:00
function FmtParamMatch: string ;
2015-01-14 11:39:44 +01:00
end ;
HeadersAttribute = class( TCustomAttribute)
private
2020-09-02 16:13:29 +02:00
FKey: string ;
FValue: string ;
2015-01-14 11:39:44 +01:00
procedure SetKey( const Value: string ) ;
procedure SetValue( const Value: string ) ;
public
constructor Create( AKey: string ; AValue: string ) ;
2020-09-02 16:13:29 +02:00
property Key: string read FKey write SetKey;
property Value: string read FValue write SetValue;
2015-01-14 11:39:44 +01:00
end ;
2015-02-17 09:40:55 +01:00
MappingAttribute = class( TCustomAttribute)
private
2020-09-02 16:13:29 +02:00
FClass: TClass;
2015-02-17 09:40:55 +01:00
public
constructor Create( AClass: TClass) ;
function GetType: TRttiType;
end ;
2015-01-14 11:39:44 +01:00
IRESTAdapter< T> = interface
[ '{AAA41F40-69DB-419B-9922-F59F990CBDB5}' ]
function ResourcesService: T;
procedure AddRequestHeaders( AObj: TRttiObject) ;
procedure AddRequestHeader( AKey: string ; AValue: string ) ;
2020-09-02 16:13:29 +02:00
procedure MapResult( AResp: IRESTResponse; AMethod: TRttiMethod;
ARTTIType: TRttiType; out AResult: TValue) ;
2015-01-14 11:39:44 +01:00
end ;
2015-06-16 15:13:59 +02:00
TRESTAdapter< T: IInvokable> = class( TVirtualInterface, IRESTAdapter< T> )
2015-01-14 11:39:44 +01:00
private
2020-09-02 16:13:29 +02:00
FRESTClient: TRESTClient;
FRESTClientOwner: boolean ;
procedure SetRESTClient( const Value: TRESTClient) ;
procedure SetRESTClientOwner( const Value: boolean ) ;
2015-01-14 11:39:44 +01:00
protected
2020-09-02 16:13:29 +02:00
procedure DoInvoke( Method: TRttiMethod; const Args: TArray< TValue> ;
out Result : TValue) ;
2015-01-14 11:39:44 +01:00
procedure AddRequestHeaders( AObj: TRttiObject) ;
procedure AddRequestHeader( AKey: string ; AValue: string ) ;
2020-09-02 16:13:29 +02:00
procedure MapResult( AResp: IRESTResponse; AMethod: TRttiMethod;
ARTTIType: TRttiType; out AResult: TValue) ;
2015-01-17 17:19:09 +01:00
function GetURL( AMethod: TRttiMethod; const Args: TArray< TValue> ) : string ;
2020-09-02 16:13:29 +02:00
function GetBodyAsString( AMethod: TRttiMethod;
const Args: TArray< TValue> ) : string ;
2015-01-14 11:39:44 +01:00
public
constructor Create;
destructor Destroy; override ;
2020-09-02 16:13:29 +02:00
function Build( ARESTClient: TRESTClient; const ARESTClientOwner: boolean = false ) : T; overload ;
function Build( const AServerName: string ; const AServerPort: Word = 8 0 ;
AIOHandler: TIdIOHandler = nil ) : T; overload ;
2015-01-14 11:39:44 +01:00
function ResourcesService: T;
2020-09-02 16:13:29 +02:00
property RESTClient: TRESTClient read FRESTClient write SetRESTClient;
property RESTClientOwner: boolean read FRESTClientOwner write SetRESTClientOwner;
2015-01-14 11:39:44 +01:00
end ;
2015-02-17 09:40:55 +01:00
IAsynchRequest = interface
[ '{3E720356-F2B7-4C32-8051-B7723263740F}' ]
2020-09-02 16:13:29 +02:00
procedure SetAlwaysProc( const Value: TProc) ;
2015-02-17 09:40:55 +01:00
procedure SetErrorProc( const Value: TProc< Exception> ) ;
procedure SetSuccessProc( const Value: TProc< TValue> ) ;
2020-09-02 16:13:29 +02:00
procedure SetSynchronized( const Value: boolean ) ;
2015-02-17 09:40:55 +01:00
2020-09-02 16:13:29 +02:00
function GetAlwaysProc: TProc;
2015-02-17 09:40:55 +01:00
function GetErrorProc: TProc< Exception> ;
function GetSuccessProc: TProc< TValue> ;
2020-09-02 16:13:29 +02:00
function GetSynchronized: boolean ;
2015-02-17 09:40:55 +01:00
2020-09-02 16:13:29 +02:00
property SuccessProc: TProc< TValue> read GetSuccessProc
write SetSuccessProc;
2015-02-17 09:40:55 +01:00
property ErrorProc: TProc< Exception> read GetErrorProc write SetErrorProc;
2020-09-02 16:13:29 +02:00
property AlwaysProc: TProc read GetAlwaysProc write SetAlwaysProc;
property Synchronized: boolean read GetSynchronized write SetSynchronized;
2015-02-17 09:40:55 +01:00
end ;
TAsynchRequest = class( TInterfacedObject, IAsynchRequest)
2015-01-19 15:28:04 +01:00
private
2020-09-02 16:13:29 +02:00
FSynchronized: boolean ;
FSuccessProc: TProc< TValue> ;
FErrorProc: TProc< Exception> ;
FAlwaysProc: TProc;
procedure SetAlwaysProc( const Value: TProc) ;
2015-01-19 15:28:04 +01:00
procedure SetErrorProc( const Value: TProc< Exception> ) ;
2015-02-17 09:40:55 +01:00
procedure SetSuccessProc( const Value: TProc< TValue> ) ;
2020-09-02 16:13:29 +02:00
procedure SetSynchronized( const Value: boolean ) ;
function GetAlwaysProc: TProc;
2015-02-17 09:40:55 +01:00
function GetErrorProc: TProc< Exception> ;
function GetSuccessProc: TProc< TValue> ;
2020-09-02 16:13:29 +02:00
function GetSynchronized: boolean ;
2015-01-19 15:28:04 +01:00
public
2020-09-02 16:13:29 +02:00
constructor Create( ASuccProc: TProc< TValue> = nil ;
AProcErr: TProc< Exception> = nil ; AProcAlways: TProc = nil ;
ASynchronized: boolean = false ) ;
property SuccessProc: TProc< TValue> read GetSuccessProc
write SetSuccessProc;
2015-02-17 09:40:55 +01:00
property ErrorProc: TProc< Exception> read GetErrorProc write SetErrorProc;
2020-09-02 16:13:29 +02:00
property AlwaysProc: TProc read GetAlwaysProc write SetAlwaysProc;
property Synchronized: boolean read GetSynchronized write SetSynchronized;
2015-01-19 15:28:04 +01:00
end ;
2015-01-14 11:39:44 +01:00
implementation
uses
2017-04-26 14:39:18 +02:00
// ObjectsMappers,
MVCFramework. Serializer. Commons,
MVCFramework. Serializer. Defaults,
2020-09-02 16:13:29 +02:00
{$IFDEF SYSTEMJSON}
2017-01-18 21:53:53 +01:00
System. JSON,
2017-04-26 14:39:18 +02:00
2020-09-02 16:13:29 +02:00
{$ELSE}
2015-01-14 11:39:44 +01:00
Data. DBXJSON,
Data. SqlExpr,
DBXCommon,
2017-04-26 14:39:18 +02:00
2020-09-02 16:13:29 +02:00
{$ENDIF}
2017-03-20 19:08:01 +01:00
MVCFramework. Rtti. Utils,
2017-01-18 21:53:53 +01:00
MVCFramework. DuckTyping,
2020-09-02 16:13:29 +02:00
Generics. Collections;
2015-01-14 11:39:44 +01:00
{ TRESTAdapter }
2020-09-02 16:13:29 +02:00
function TRESTAdapter< T> . Build( ARESTClient: TRESTClient;
const ARESTClientOwner: boolean = false ) : T;
2015-01-14 11:39:44 +01:00
begin
RESTClient : = ARESTClient;
2015-06-16 15:13:59 +02:00
RESTClientOwner : = ARESTClientOwner;
2015-01-14 11:39:44 +01:00
Result : = ResourcesService;
end ;
procedure TRESTAdapter< T> . AddRequestHeader( AKey, AValue: string ) ;
begin
2020-09-02 16:13:29 +02:00
if CompareText( AKey, 'ContentType' ) = 0 then
FRESTClient. ContentType( AValue)
else if CompareText( AKey, 'ContentEncoding' ) = 0 then
FRESTClient. ContentEncoding( AValue)
else if CompareText( AKey, 'Accept' ) = 0 then
FRESTClient. Accept( AValue)
2015-01-14 11:39:44 +01:00
else
2020-09-02 16:13:29 +02:00
FRESTClient. RequestHeaders. Values[ AKey] : = AValue;
2015-01-14 11:39:44 +01:00
end ;
procedure TRESTAdapter< T> . AddRequestHeaders( AObj: TRttiObject) ;
var
2020-09-02 16:13:29 +02:00
_attr: TCustomAttribute;
2015-01-14 11:39:44 +01:00
begin
2020-09-02 16:13:29 +02:00
for _attr in AObj. GetAttributes do
if _attr is HeadersAttribute then
AddRequestHeader( HeadersAttribute( _attr) . Key,
HeadersAttribute( _attr) . Value) ;
2015-01-14 11:39:44 +01:00
end ;
2020-09-02 16:13:29 +02:00
function TRESTAdapter< T> . Build( const AServerName: string ;
const AServerPort: Word ; AIOHandler: TIdIOHandler) : T;
2015-01-14 11:39:44 +01:00
var
2020-09-02 16:13:29 +02:00
ARESTClient: TRESTClient;
2015-01-14 11:39:44 +01:00
begin
2020-09-02 16:13:29 +02:00
ARESTClient : = TRESTClient. Create( AServerName, AServerPort, AIOHandler) ;
Result : = Build( ARESTClient, true ) ;
2015-01-14 11:39:44 +01:00
end ;
constructor TRESTAdapter< T> . Create;
begin
2015-06-16 15:13:59 +02:00
inherited Create( TypeInfo( T) , DoInvoke) ;
2015-01-14 11:39:44 +01:00
end ;
destructor TRESTAdapter< T> . Destroy;
begin
2016-06-22 17:49:16 +02:00
// Ezequiel J. M<> ller (If it is created outside, it must be destroyed out)
// d.spinetti added RESTClientOwner to manage desctruction of RESTClient and free its associated memory
2020-09-02 16:13:29 +02:00
if RESTClientOwner and Assigned( FRESTClient) then
FRESTClient. Free;
2015-01-14 11:39:44 +01:00
inherited ;
end ;
2020-09-02 16:13:29 +02:00
procedure TRESTAdapter< T> . DoInvoke( Method: TRttiMethod;
const Args: TArray< TValue> ; out Result : TValue) ;
2015-01-14 11:39:44 +01:00
var
2020-09-02 16:13:29 +02:00
Resp: IRESTResponse;
_restresourceattr: RESTResourceAttribute;
URL: string ;
Body: string ;
AsynchClass: IAsynchRequest;
_mappingattr: MappingAttribute;
2015-01-14 11:39:44 +01:00
begin
// Implementation of RESTClient DoGet DoPut ecc...
2020-09-02 16:13:29 +02:00
if not TRttiUtils. HasAttribute< RESTResourceAttribute> ( Method,
_restresourceattr) then
raise Exception. CreateFmt( 'No REST Resource specified in method %s' ,
[ Method. Name ] ) ;
2015-01-14 11:39:44 +01:00
// headers can be more than one
2020-09-02 16:13:29 +02:00
// FRESTClient.RequestHeaders.Clear; //Ezequiel J. M<> ller (You can not clear the header, because I can use other.)
2015-01-14 11:39:44 +01:00
// Interface
2017-03-01 21:40:57 +01:00
AddRequestHeaders( TRttiUtils. GlContext. GetType( TypeInfo( T) ) ) ;
2015-01-14 11:39:44 +01:00
// Method
AddRequestHeaders( Method) ;
2020-09-02 16:13:29 +02:00
// URL and Body
URL : = GetURL( Method, Args) ;
Body : = GetBodyAsString( Method, Args) ;
2015-01-17 17:19:09 +01:00
2015-01-19 15:28:04 +01:00
// Asynch way to do
2020-09-02 16:13:29 +02:00
if Args[ Length( Args) - 1 ] . TryAsType< IAsynchRequest> ( AsynchClass) then
2015-02-17 09:40:55 +01:00
begin
2020-09-02 16:13:29 +02:00
FRESTClient. Asynch(
procedure( ARESTResponse: IRESTResponse)
2015-01-19 15:28:04 +01:00
var
2020-09-02 16:13:29 +02:00
ResValue: TValue;
2015-01-19 15:28:04 +01:00
begin
2020-09-02 16:13:29 +02:00
if TRttiUtils. HasAttribute< MappingAttribute> ( Method, _mappingattr) then
MapResult( ARESTResponse, Method, _mappingattr. GetType, ResValue)
2015-02-17 09:40:55 +01:00
else
2020-09-02 16:13:29 +02:00
ResValue : = TValue. From( ARESTResponse) ;
if Assigned( AsynchClass. SuccessProc) then
AsynchClass. SuccessProc( ResValue) ;
end , AsynchClass. ErrorProc, AsynchClass. AlwaysProc,
AsynchClass. Synchronized) ;
2015-02-17 09:40:55 +01:00
end ;
2015-01-19 15:28:04 +01:00
2020-09-02 16:13:29 +02:00
case _restresourceattr. HTTPMethodType of
2015-01-14 11:39:44 +01:00
httpGET:
2020-09-02 16:13:29 +02:00
Resp : = FRESTClient. doGET( URL, [ ] ) ;
2015-01-14 11:39:44 +01:00
httpPUT:
2020-09-02 16:13:29 +02:00
Resp : = FRESTClient. doPUT( URL, [ ] , Body) ;
2015-01-14 11:39:44 +01:00
httpPOST:
2020-09-02 16:13:29 +02:00
Resp : = FRESTClient. doPOST( URL, [ ] , Body) ;
2017-11-16 22:49:38 +01:00
httpDELETE:
2020-09-02 16:13:29 +02:00
Resp : = FRESTClient. doDELETE( URL, [ ] ) ;
2015-01-14 11:39:44 +01:00
end ;
2015-01-17 17:19:09 +01:00
// if the response code is > 400 raise exception
2020-09-02 16:13:29 +02:00
// if Resp.ResponseCode >= 400 then
2015-01-17 17:19:09 +01:00
// raise Exception.CreateFmt
// ('Error on execute request ''%s''. Message: %d %s ',
2020-09-02 16:13:29 +02:00
// [URL, Resp.ResponseCode, Resp.BodyAsString]);
2015-01-17 17:19:09 +01:00
2015-01-14 11:39:44 +01:00
// if is a procedure no need a return type
if Assigned( Method. ReturnType) then
2020-09-02 16:13:29 +02:00
MapResult( Resp, Method, Method. ReturnType, Result ) ;
2015-01-14 11:39:44 +01:00
end ;
2015-02-17 09:40:55 +01:00
function TRESTAdapter< T> . GetBodyAsString( AMethod: TRttiMethod;
const Args: TArray< TValue> ) : string ;
2015-01-17 17:19:09 +01:00
var
_parameters: TArray< TRttiParameter> ;
I: Integer ;
_parameter: TRttiParameter;
_param: BodyAttribute;
2017-04-26 14:39:18 +02:00
_attrlistof: MVCListOfAttribute;
2015-01-17 17:19:09 +01:00
Arg: TValue;
2015-01-14 11:39:44 +01:00
begin
2015-01-17 17:19:09 +01:00
_parameters : = AMethod. GetParameters;
for I : = 0 to Length( _parameters) - 1 do
begin
_parameter : = _parameters[ I] ;
// ARG := ARGS[I+1] because
// Args RTTI for the arguments of the interface method that has been called. The first argument (located at index 0) represents the interface instance itself.
Arg : = Args[ I + 1 ] ;
2017-03-01 21:40:57 +01:00
if TRttiUtils. HasAttribute< BodyAttribute> ( _parameter, _param) then
2015-01-19 15:28:04 +01:00
try
if Arg. IsObject then
2015-12-22 12:15:43 +01:00
begin
2017-04-26 14:39:18 +02:00
if TRttiUtils. HasAttribute< MVCListOfAttribute> ( AMethod, _attrlistof) then
Exit(
GetDefaultSerializer. SerializeCollection( Arg. AsObject)
2020-09-02 16:13:29 +02:00
{ Mapper.ObjectListToJSONArrayString(WrapAsList(Arg.AsObject), true) }
2017-04-26 14:39:18 +02:00
)
2015-12-22 12:15:43 +01:00
else
2017-04-26 14:39:18 +02:00
Exit(
GetDefaultSerializer. SerializeObject( Arg. AsObject)
{ Mapper.ObjectToJSONObjectString(Arg.AsObject) }
) ;
2015-12-22 12:15:43 +01:00
end
2015-01-19 15:28:04 +01:00
else
2017-03-01 21:40:57 +01:00
Exit( TRttiUtils. TValueAsString( Arg, '' , '' ) ) ;
2015-01-19 15:28:04 +01:00
finally
if _param. OwnsObject and Arg. IsObject then
2017-01-18 21:53:53 +01:00
begin
2017-04-26 14:39:18 +02:00
2020-09-02 16:13:29 +02:00
{$HINTS OFF}
2015-01-19 15:28:04 +01:00
Arg. AsObject. Free;
2017-04-26 14:39:18 +02:00
2020-09-02 16:13:29 +02:00
{$HINTS ON}
2017-01-18 21:53:53 +01:00
end ;
2015-01-19 15:28:04 +01:00
end ;
2015-01-17 17:19:09 +01:00
end ;
2015-01-14 11:39:44 +01:00
end ;
2015-02-17 09:40:55 +01:00
function TRESTAdapter< T> . GetURL( AMethod: TRttiMethod;
const Args: TArray< TValue> ) : string ;
2015-01-14 11:39:44 +01:00
var
2015-01-17 17:19:09 +01:00
_restresourceattr: RESTResourceAttribute;
IURL: string ;
SplitUrl: TArray< string > ;
URLDict: TDictionary< string , string > ;
Split: string ;
_parameters: TArray< TRttiParameter> ;
2015-01-14 11:39:44 +01:00
I: Integer ;
_parameter: TRttiParameter;
_param: ParamAttribute;
2015-01-17 17:19:09 +01:00
Arg: TValue;
2015-01-14 11:39:44 +01:00
begin
2017-03-01 21:40:57 +01:00
_restresourceattr : = TRttiUtils. GetAttribute< RESTResourceAttribute> ( AMethod) ;
2015-01-17 17:19:09 +01:00
IURL : = _restresourceattr. URL;
SplitUrl : = IURL. Split( [ URL_SEPARATOR] ) ;
URLDict : = TDictionary< string , string > . Create;
try
for Split in SplitUrl do
if not Split. IsEmpty then
URLDict. Add( Split, Split) ;
_parameters : = AMethod. GetParameters;
// ARG := ARGS[I+1] because
// Args RTTI for the arguments of the interface method that has been called. The first argument (located at index 0) represents the interface instance itself.
for I : = 0 to Length( _parameters) - 1 do
begin
_parameter : = _parameters[ I] ;
Arg : = Args[ I + 1 ] ;
2017-03-01 21:40:57 +01:00
if TRttiUtils. HasAttribute< ParamAttribute> ( _parameter, _param) then
URLDict[ _param. FmtParamMatch] : = TRttiUtils. TValueAsString( Arg,
2015-02-17 09:40:55 +01:00
_param. ParamType, _param. CustomFormat) ;
2015-01-17 17:19:09 +01:00
end ;
for Split in SplitUrl do
if not Split. IsEmpty then
Result : = Result + URL_SEPARATOR + URLDict[ Split] ;
2020-09-02 16:13:29 +02:00
if IURL. EndsWith( URL_SEPARATOR) and not( Result . EndsWith( URL_SEPARATOR) ) then
2015-01-17 17:19:09 +01:00
Result : = Result + URL_SEPARATOR;
finally
URLDict. Free;
2015-01-14 11:39:44 +01:00
end ;
end ;
2020-09-02 16:13:29 +02:00
procedure TRESTAdapter< T> . MapResult( AResp: IRESTResponse; AMethod: TRttiMethod; ARTTIType: TRttiType;
2020-01-08 20:34:02 +01:00
out AResult: TValue) ;
2015-01-14 11:39:44 +01:00
var
2017-04-26 14:39:18 +02:00
_attrlistof: MVCListOfAttribute;
2015-01-14 11:39:44 +01:00
begin
2015-02-17 09:40:55 +01:00
if ARTTIType. TypeKind = tkClass then
2015-01-14 11:39:44 +01:00
begin
2015-01-17 17:19:09 +01:00
// ListOf
2017-04-26 14:39:18 +02:00
if TRttiUtils. HasAttribute< MVCListOfAttribute> ( AMethod, _attrlistof) then
2015-01-17 17:19:09 +01:00
begin
2017-03-01 21:40:57 +01:00
AResult : = TRttiUtils. CreateObject( ARTTIType. QualifiedName) ;
2020-09-02 16:13:29 +02:00
GetDefaultSerializer. DeserializeCollection( AResp. BodyAsString, AResult. AsObject, _attrlistof. Value) ;
2015-01-17 17:19:09 +01:00
end
// JSONValue
2015-02-17 09:40:55 +01:00
else if ARTTIType. AsInstance. MetaclassType. InheritsFrom( TJSONValue) then
2017-04-26 14:39:18 +02:00
begin
2020-09-02 16:13:29 +02:00
AResult : = TJSONObject. ParseJSONValue( AResp. BodyAsString) ;
2015-01-17 17:19:09 +01:00
// Object
2017-04-26 14:39:18 +02:00
end
2015-01-17 17:19:09 +01:00
else
2017-04-26 14:39:18 +02:00
begin
AResult : = TRttiUtils. CreateObject( ARTTIType. QualifiedName) ;
2020-09-02 16:13:29 +02:00
GetDefaultSerializer. DeserializeObject( AResp. BodyAsString, AResult. AsObject) ;
2017-04-26 14:39:18 +02:00
end ;
2015-01-14 11:39:44 +01:00
end
else
2020-09-02 16:13:29 +02:00
// IRESTResponse
if ARTTIType. QualifiedName = TRttiUtils. GlContext. GetType( TypeInfo( IRESTResponse) )
2015-02-17 09:40:55 +01:00
. QualifiedName then
2020-01-08 20:34:02 +01:00
begin
2015-01-17 17:19:09 +01:00
AResult : = AResult. From( AResp)
2020-01-08 20:34:02 +01:00
end
2020-09-02 16:13:29 +02:00
else // else a simple BodyAsString
2020-01-08 20:34:02 +01:00
begin
2020-09-02 16:13:29 +02:00
AResult : = AResp. BodyAsString
2020-01-08 20:34:02 +01:00
end ;
2015-01-14 11:39:44 +01:00
end ;
function TRESTAdapter< T> . ResourcesService: T;
var
pInfo: PTypeInfo;
begin
pInfo : = TypeInfo( T) ;
if QueryInterface( GetTypeData( pInfo) . Guid, Result ) < > 0 then
begin
2017-01-18 21:53:53 +01:00
raise Exception. Create( 'RESTAdapter is unable to cast to its interface' ) ;
2015-01-14 11:39:44 +01:00
end ;
end ;
2020-09-02 16:13:29 +02:00
procedure TRESTAdapter< T> . SetRESTClient( const Value: TRESTClient) ;
begin
FRESTClient : = Value;
end ;
procedure TRESTAdapter< T> . SetRESTClientOwner( const Value: boolean ) ;
begin
FRESTClientOwner : = Value;
end ;
2015-01-14 11:39:44 +01:00
{ RESTResourceAttribute }
2015-02-17 09:40:55 +01:00
constructor RESTResourceAttribute. Create( AMVCHTTPMethod: TMVCHTTPMethodType;
AURL: string ) ;
2015-01-14 11:39:44 +01:00
begin
2020-09-02 16:13:29 +02:00
FURL : = AURL;
FHTTPMethodType : = AMVCHTTPMethod;
2015-01-14 11:39:44 +01:00
end ;
2015-02-17 09:40:55 +01:00
procedure RESTResourceAttribute. SetHTTPMethodType
( const Value: TMVCHTTPMethodType) ;
2015-01-14 11:39:44 +01:00
begin
2020-09-02 16:13:29 +02:00
FHTTPMethodType : = Value;
2015-01-14 11:39:44 +01:00
end ;
procedure RESTResourceAttribute. SetURL( const Value: string ) ;
begin
2020-09-02 16:13:29 +02:00
FURL : = Value;
2015-01-14 11:39:44 +01:00
end ;
{ BodyAttribute }
2020-09-02 16:13:29 +02:00
constructor BodyAttribute. Create( AOwnsObject: boolean ) ;
2015-01-14 11:39:44 +01:00
begin
2015-01-17 17:19:09 +01:00
inherited Create;
2015-01-14 11:39:44 +01:00
FOwnsObject : = AOwnsObject;
end ;
2020-09-02 16:13:29 +02:00
procedure BodyAttribute. SetOwnsObject( const Value: boolean ) ;
2015-01-14 11:39:44 +01:00
begin
FOwnsObject : = Value;
end ;
{ ParamAttribute }
2015-02-17 09:40:55 +01:00
constructor ParamAttribute. Create( AParamMatch: string ;
AParamType, ACustomFormat: string ) ;
2015-01-14 11:39:44 +01:00
begin
2015-01-17 17:19:09 +01:00
inherited Create;
2020-09-02 16:13:29 +02:00
FParamMatch : = AParamMatch;
FParamType : = AParamType;
FCustomFormat : = ACustomFormat;
2015-01-14 11:39:44 +01:00
end ;
2015-01-17 17:19:09 +01:00
function ParamAttribute. FmtParamMatch: string ;
begin
Result : = '{' + ParamMatch + '}' ;
end ;
2015-01-14 11:39:44 +01:00
procedure ParamAttribute. SetCustomFormat( const Value: string ) ;
begin
2020-09-02 16:13:29 +02:00
FCustomFormat : = Value;
2015-01-14 11:39:44 +01:00
end ;
2015-01-17 17:19:09 +01:00
procedure ParamAttribute. SetParamMatch( const Value: string ) ;
begin
2020-09-02 16:13:29 +02:00
FParamMatch : = Value;
2015-01-17 17:19:09 +01:00
end ;
2015-01-14 11:39:44 +01:00
procedure ParamAttribute. SetParamType( const Value: string ) ;
begin
2020-09-02 16:13:29 +02:00
FParamType : = Value;
2015-01-14 11:39:44 +01:00
end ;
{ HeadersAttribute }
constructor HeadersAttribute. Create( AKey: string ; AValue: string ) ;
begin
2020-09-02 16:13:29 +02:00
FKey : = AKey;
FValue : = AValue;
2015-01-14 11:39:44 +01:00
end ;
procedure HeadersAttribute. SetKey( const Value: string ) ;
begin
2020-09-02 16:13:29 +02:00
FKey : = Value;
2015-01-14 11:39:44 +01:00
end ;
procedure HeadersAttribute. SetValue( const Value: string ) ;
begin
2020-09-02 16:13:29 +02:00
FValue : = Value;
2015-01-14 11:39:44 +01:00
end ;
2015-01-19 15:28:04 +01:00
{ TAsynchRequest }
2020-09-02 16:13:29 +02:00
constructor TAsynchRequest. Create( ASuccProc: TProc< TValue> = nil ;
AProcErr: TProc< Exception> = nil ; AProcAlways: TProc = nil ;
ASynchronized: boolean = false ) ;
2015-01-19 15:28:04 +01:00
begin
inherited Create;
2020-09-02 16:13:29 +02:00
FSuccessProc : = ASuccProc;
FErrorProc : = AProcErr;
FAlwaysProc : = AProcAlways;
FSynchronized : = ASynchronized;
end ;
function TAsynchRequest. GetAlwaysProc: TProc;
begin
Result : = FAlwaysProc;
2015-02-17 09:40:55 +01:00
end ;
function TAsynchRequest. GetErrorProc: TProc< Exception> ;
begin
2020-09-02 16:13:29 +02:00
Result : = FErrorProc;
2015-02-17 09:40:55 +01:00
end ;
function TAsynchRequest. GetSuccessProc: TProc< TValue> ;
begin
2020-09-02 16:13:29 +02:00
Result : = FSuccessProc;
end ;
function TAsynchRequest. GetSynchronized: boolean ;
begin
Result : = FSynchronized;
2015-02-17 09:40:55 +01:00
end ;
2020-09-02 16:13:29 +02:00
procedure TAsynchRequest. SetAlwaysProc( const Value: TProc) ;
2015-01-19 15:28:04 +01:00
begin
2020-09-02 16:13:29 +02:00
FAlwaysProc : = Value;
2015-01-19 15:28:04 +01:00
end ;
procedure TAsynchRequest. SetErrorProc( const Value: TProc< Exception> ) ;
begin
2020-09-02 16:13:29 +02:00
FErrorProc : = Value;
2015-01-19 15:28:04 +01:00
end ;
2015-02-17 09:40:55 +01:00
procedure TAsynchRequest. SetSuccessProc( const Value: TProc< TValue> ) ;
2015-01-19 15:28:04 +01:00
begin
2020-09-02 16:13:29 +02:00
FSuccessProc : = Value;
2015-01-19 15:28:04 +01:00
end ;
2020-09-02 16:13:29 +02:00
procedure TAsynchRequest. SetSynchronized( const Value: boolean ) ;
2015-01-19 15:28:04 +01:00
begin
2020-09-02 16:13:29 +02:00
FSynchronized : = Value;
2015-01-19 15:28:04 +01:00
end ;
2015-02-17 09:40:55 +01:00
{ MappingAttribute }
constructor MappingAttribute. Create( AClass: TClass) ;
begin
2020-09-02 16:13:29 +02:00
FClass : = AClass;
2015-02-17 09:40:55 +01:00
end ;
function MappingAttribute. GetType: TRttiType;
begin
2020-09-02 16:13:29 +02:00
Result : = TRttiUtils. GlContext. GetType( FClass) ;
2015-02-17 09:40:55 +01:00
end ;
2015-01-14 11:39:44 +01:00
end .