xtool/contrib/mORMot/SQLite3/Samples/27 - CrossPlatform Clients/mORMotClient.pas

340 lines
11 KiB
ObjectPascal

/// remote access to a mORMot server using SynCrossPlatform* units
// - retrieved from http://localhost:888/root/wrapper/CrossPlatform/mORMotClient.pas
// at 2014-12-10 21:28:46 using "CrossPlatform.pas.mustache" template
unit mORMotClient;
{
WARNING:
This unit has been generated by a mORMot 1.18.626 server.
Any manual modification of this file may be lost after regeneration.
Synopse mORMot framework. Copyright (C) 2014 Arnaud Bouchez
Synopse Informatique - https://synopse.info
This unit is released under a MPL/GPL/LGPL tri-license,
and therefore may be freely included in any application.
This unit would work on Delphi 6 and later, under all supported platforms
(including MacOSX, and NextGen iPhone/iPad), and the Free Pascal Compiler.
}
interface
uses
SynCrossPlatformJSON,
SynCrossPlatformSpecific,
SynCrossPlatformREST;
type // define some enumeration types, used below
TPeopleSexe = (sFemale, sMale);
TRecordEnum = (reOne, reTwo, reLast);
type // define some record types, used as properties below
TTestCustomJSONArraySimpleArray = record
F: String;
G: array of String;
H: record
H1: Integer;
H2: String;
H3: record
H3a: Boolean;
H3b: TSQLRawBlob;
end;
end;
I: TDateTime;
J: array of record
J1: Byte;
J2: TGUID;
J3: TRecordEnum;
end;
end;
TSimpleRecord = record
A: Integer;
B: Integer;
C: String;
end;
type // define some dynamic array types, used as properties below
TPeopleSexeDynArray = array of Byte;
TSimpleRecordDynArray = array of TSimpleRecord;
type
/// map "People" table
TSQLRecordPeople = class(TSQLRecord)
protected
fFirstName: String;
fLastName: String;
fData: TSQLRawBlob;
fYearOfBirth: Integer;
fYearOfDeath: Word;
fSexe: TPeopleSexe;
fSimple: TTestCustomJSONArraySimpleArray;
public
property Simple: TTestCustomJSONArraySimpleArray read fSimple write fSimple;
published
property FirstName: String read fFirstName write fFirstName;
property LastName: String read fLastName write fLastName;
property Data: TSQLRawBlob read fData write fData;
property YearOfBirth: Integer read fYearOfBirth write fYearOfBirth;
property YearOfDeath: Word read fYearOfDeath write fYearOfDeath;
property Sexe: TPeopleSexe read fSexe write fSexe;
end;
/// service implemented by TServiceCalculator
// - you can access this service as such:
// !var aCalculator: ICalculator;
// !begin
// ! aCalculator := TCalculator.Create(aClient);
// ! // now you can use aCalculator methods
// !...
ICalculator = interface(IServiceAbstract)
['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}']
function Add(const n1: Integer; const n2: Integer): Integer;
procedure ToText(const Value: Currency; const Curr: String; var Sexe: TPeopleSexe; var Name: String);
function RecordToText(var Rec: TTestCustomJSONArraySimpleArray): String;
function GetPeople(const id: TID; out People: TSQLRecordPeople; out Sexes: TPeopleSexeDynArray; var arr: TSimpleRecordDynArray): Boolean;
end;
/// implements ICalculator from http://localhost:888/root/Calculator
// - this service will run in sicShared mode
TServiceCalculator = class(TServiceClientAbstract,ICalculator)
public
constructor Create(aClient: TSQLRestClientURI); override;
function Add(const n1: Integer; const n2: Integer): Integer;
procedure ToText(const Value: Currency; const Curr: String; var Sexe: TPeopleSexe; var Name: String);
function RecordToText(var Rec: TTestCustomJSONArraySimpleArray): String;
function GetPeople(const id: TID; out People: TSQLRecordPeople; out Sexes: TPeopleSexeDynArray; var arr: TSimpleRecordDynArray): Boolean;
end;
const
/// the server port, corresponding to http://localhost:888
SERVER_PORT = 888;
/// return the database Model corresponding to this server
function GetModel: TSQLModel;
/// create a TSQLRestClientHTTP instance and connect to the server
// - it will use by default port 888
// - secure connection will be established via TSQLRestServerAuthenticationDefault
// with the supplied credentials - on connection or authentication error,
// this function will raise a corresponding exception
function GetClient(const aServerAddress, aUserName,aPassword: string;
aServerPort: integer=SERVER_PORT): TSQLRestClientHTTP;
// publish some low-level helpers for variant conversion
// - used internally: you should not need those functions in your end-user code
function Variant2TPeopleSexe(const _variant: variant): TPeopleSexe;
function Variant2TRecordEnum(const _variant: variant): TRecordEnum;
function Variant2TTestCustomJSONArraySimpleArray(_variant: variant): TTestCustomJSONArraySimpleArray;
function TTestCustomJSONArraySimpleArray2Variant(const _record: TTestCustomJSONArraySimpleArray): variant;
function Variant2TSimpleRecord(_variant: variant): TSimpleRecord;
function TSimpleRecord2Variant(const _record: TSimpleRecord): variant;
function Variant2TPeopleSexeDynArray(const _variant: variant): TPeopleSexeDynArray;
function TPeopleSexeDynArray2Variant(const _array: TPeopleSexeDynArray): variant;
function Variant2TSimpleRecordDynArray(const _variant: variant): TSimpleRecordDynArray;
function TSimpleRecordDynArray2Variant(const _array: TSimpleRecordDynArray): variant;
implementation
{ Some helpers for enumerates types }
function Variant2TPeopleSexe(const _variant: variant): TPeopleSexe;
begin
result := TPeopleSexe(VariantToEnum(_variant,['sFemale','sMale']));
end;
function Variant2TRecordEnum(const _variant: variant): TRecordEnum;
begin
result := TRecordEnum(VariantToEnum(_variant,['reOne','reTwo','reLast']));
end;
{ Some helpers for record types }
function Variant2TTestCustomJSONArraySimpleArray(_variant: variant): TTestCustomJSONArraySimpleArray;
var _a: integer;
_arr: PJSONVariantData;
begin
result.F := _variant.F;
_arr := JSONVariantDataSafe(_variant.G,jvArray);
SetLength(result.G,_arr^.Count);
for _a := 0 to high(result.G) do
result.G[_a] := _arr^.Values[_a];
result.H.H1 := _variant.H.H1;
result.H.H2 := _variant.H.H2;
result.H.H3.H3a := _variant.H.H3.H3a;
result.H.H3.H3b := VariantToBlob(_variant.H.H3.H3b);
result.I := Iso8601ToDateTime(_variant.I);
_arr := JSONVariantDataSafe(_variant.J,jvArray);
SetLength(result.J,_arr^.Count);
for _a := 0 to high(result.J) do
with result.J[_a] do begin
J1 := _arr^.Values[_a].J1;
J2 := VariantToGUID(_arr^.Values[_a].J2);
J3 := Variant2TRecordEnum(_arr^.Values[_a].J3);
end;
end;
function TTestCustomJSONArraySimpleArray2Variant(const _record: TTestCustomJSONArraySimpleArray): variant;
var i: integer;
res: TJSONVariantData;
begin
res.Init;
res.SetPath('F',_record.F);
with res.EnsureData('G')^ do
for i := 0 to high(_record.G) do
AddValue(_record.G[i]);
res.SetPath('H.H1',_record.H.H1);
res.SetPath('H.H2',_record.H.H2);
res.SetPath('H.H3.H3a',_record.H.H3.H3a);
res.SetPath('H.H3.H3b',BlobToVariant(_record.H.H3.H3b));
res.SetPath('I',DateTimeToIso8601(_record.I));
with res.EnsureData('J')^ do
for i := 0 to high(_record.J) do
with AddItem^, _record.J[i] do begin
AddNameValue('J1',J1);
AddNameValue('J2',GUIDToVariant(J2));
AddNameValue('J3',ord(J3));
end;
result := variant(res);
end;
function Variant2TSimpleRecord(_variant: variant): TSimpleRecord;
begin
result.A := _variant.A;
result.B := _variant.B;
result.C := _variant.C;
end;
function TSimpleRecord2Variant(const _record: TSimpleRecord): variant;
var res: TJSONVariantData;
begin
res.Init;
res.SetPath('A',_record.A);
res.SetPath('B',_record.B);
res.SetPath('C',_record.C);
result := variant(res);
end;
{ Some helpers for dynamic array types }
function Variant2TPeopleSexeDynArray(const _variant: variant): TPeopleSexeDynArray;
var i: integer;
arr: PJSONVariantData;
begin
arr := JSONVariantDataSafe(_variant,jvArray);
SetLength(result,arr^.Count);
for i := 0 to arr^.Count-1 do
result[i] := (arr^.Values[i]);
end;
function TPeopleSexeDynArray2Variant(const _array: TPeopleSexeDynArray): variant;
var i: integer;
res: TJSONVariantData;
begin
res.Init;
for i := 0 to high(_array) do
res.AddValue((_array[i]));
result := variant(res);
end;
function Variant2TSimpleRecordDynArray(const _variant: variant): TSimpleRecordDynArray;
var i: integer;
arr: PJSONVariantData;
begin
arr := JSONVariantDataSafe(_variant,jvArray);
SetLength(result,arr^.Count);
for i := 0 to arr^.Count-1 do
result[i] := Variant2TSimpleRecord(arr^.Values[i]);
end;
function TSimpleRecordDynArray2Variant(const _array: TSimpleRecordDynArray): variant;
var i: integer;
res: TJSONVariantData;
begin
res.Init;
for i := 0 to high(_array) do
res.AddValue(TSimpleRecord2Variant(_array[i]));
result := variant(res);
end;
function GetModel: TSQLModel;
begin
result := TSQLModel.Create([TSQLAuthUser,TSQLAuthGroup,TSQLRecordPeople],'root');
end;
function GetClient(const aServerAddress, aUserName,aPassword: string;
aServerPort: integer): TSQLRestClientHTTP;
begin
result := TSQLRestClientHTTP.Create(aServerAddress,aServerPort,GetModel,true); // aOwnModel=true
try
if (not result.Connect) or (result.ServerTimeStamp=0) then
raise ERestException.CreateFmt('Impossible to connect to %s:%d server',
[aServerAddress,aServerPort]);
if not result.SetUser(TSQLRestServerAuthenticationDefault,aUserName,aPassword) then
raise ERestException.CreateFmt('%s:%d server rejected "%s" credentials',
[aServerAddress,aServerPort,aUserName]);
except
result.Free;
raise;
end;
end;
{ TServiceCalculator }
constructor TServiceCalculator.Create(aClient: TSQLRestClientURI);
begin
fServiceName := 'Calculator';
fServiceURI := 'Calculator';
fInstanceImplementation := sicShared;
fContractExpected := '814F1362B19B2F4D';
inherited Create(aClient);
end;
function TServiceCalculator.Add(const n1: Integer; const n2: Integer): Integer;
var res: TVariantDynArray;
begin
fClient.CallRemoteService(self,'Add',1, // raise EServiceException on error
[n1,n2],res);
Result := res[0];
end;
procedure TServiceCalculator.ToText(const Value: Currency; const Curr: String; var Sexe: TPeopleSexe; var Name: String);
var res: TVariantDynArray;
begin
fClient.CallRemoteService(self,'ToText',2, // raise EServiceException on error
[Value,Curr,ord(Sexe),Name],res);
Sexe := Variant2TPeopleSexe(res[0]);
Name := res[1];
end;
function TServiceCalculator.RecordToText(var Rec: TTestCustomJSONArraySimpleArray): String;
var res: TVariantDynArray;
begin
fClient.CallRemoteService(self,'RecordToText',2, // raise EServiceException on error
[TTestCustomJSONArraySimpleArray2Variant(Rec)],res);
Rec := Variant2TTestCustomJSONArraySimpleArray(res[0]);
Result := res[1];
end;
function TServiceCalculator.GetPeople(const id: TID; out People: TSQLRecordPeople; out Sexes: TPeopleSexeDynArray; var arr: TSimpleRecordDynArray): Boolean;
var res: TVariantDynArray;
begin
fClient.CallRemoteService(self,'GetPeople',4, // raise EServiceException on error
[id,TSimpleRecordDynArray2Variant(arr)],res);
People := TSQLRecordPeople.CreateFromVariant(res[0]);
Sexes := Variant2TPeopleSexeDynArray(res[1]);
arr := Variant2TSimpleRecordDynArray(res[2]);
Result := res[3];
end;
end.