/// 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.