340 lines
11 KiB
ObjectPascal
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. |