source upload
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
xcopy ..\..\..\CrossPlatform\SynCrossPlatformSpecific.pas "c:\ProgramData\Optimale Systemer AS\Smart Mobile Studio\Libraries" /Y
|
||||
xcopy ..\..\..\CrossPlatform\SynCrossPlatformCrypto.pas "c:\ProgramData\Optimale Systemer AS\Smart Mobile Studio\Libraries" /Y
|
||||
xcopy ..\..\..\CrossPlatform\SynCrossPlatformREST.pas "c:\ProgramData\Optimale Systemer AS\Smart Mobile Studio\Libraries" /Y
|
||||
pause
|
@@ -0,0 +1,5 @@
|
||||
rem To be used to synchronize units modified within SMS IDE
|
||||
xcopy "c:\ProgramData\Optimale Systemer AS\Smart Mobile Studio\Libraries\SynCrossPlatformSpecific.pas" ..\..\..\CrossPlatform /Y
|
||||
xcopy "c:\ProgramData\Optimale Systemer AS\Smart Mobile Studio\Libraries\SynCrossPlatformCrypto.pas" ..\..\..\CrossPlatform /Y
|
||||
xcopy "c:\ProgramData\Optimale Systemer AS\Smart Mobile Studio\Libraries\SynCrossPlatformREST.pas" ..\..\..\CrossPlatform /Y
|
||||
pause
|
@@ -0,0 +1,113 @@
|
||||
unit LoginForm;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SmartCL.System, SmartCL.Graphics, SmartCL.Components, SmartCL.Forms,
|
||||
SmartCL.Fonts, SmartCL.Borders, SmartCL.Application,
|
||||
SynCrossPlatformREST, SmartTests,
|
||||
SmartCL.Controls.Label, SmartCL.Controls.Editbox, SmartCL.Controls.Panel,
|
||||
SmartCL.Controls.Button, w3c.date;
|
||||
|
||||
type
|
||||
TLoginForm=class(TW3form)
|
||||
procedure W3Button1Click(Sender: TObject);
|
||||
procedure ConnectClick(Sender: TObject);
|
||||
private
|
||||
{$I 'LoginForm:intf'}
|
||||
protected
|
||||
procedure InitializeForm; override;
|
||||
procedure InitializeObject; override;
|
||||
procedure Resize; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
mORMotClient; // unit generated by the server!
|
||||
|
||||
{ TLoginForm }
|
||||
|
||||
procedure TLoginForm.InitializeForm;
|
||||
begin
|
||||
inherited;
|
||||
// this is a good place to initialize components
|
||||
end;
|
||||
|
||||
procedure TLoginForm.InitializeObject;
|
||||
begin
|
||||
inherited;
|
||||
{$I 'LoginForm:impl'}
|
||||
LogonPassword.InputType := itPassword;
|
||||
end;
|
||||
|
||||
procedure TLoginForm.ConnectClick(Sender: TObject);
|
||||
var model: TSQLModel;
|
||||
begin
|
||||
BrowserAPI.console.time('ORM');
|
||||
writeln('Creating Data Model');
|
||||
model := GetModel;
|
||||
model.GetTableIndexExisting(TSQLRecordPeople);
|
||||
var people := new TSQLRecordPeople;
|
||||
var s := model.InfoExisting(people.RecordClass).ToJSONAdd(nil,people,true,'');
|
||||
assert(s='{"RowID":0,"FirstName":"","LastName":"","YearOfBirth":0,"YearOfDeath":0,'+
|
||||
'"Sexe":0,"Simple":{"F":"","G":[],"H":{"H1":0,"H2":"","H3":{"H3a":false,"H3b":null}},"I":"","J":[]}}');
|
||||
s := '{"RowID":10,"FirstName":"ab\"c","LastName":"def","YearOfBirth":20,"YearOfDeath":30,'+
|
||||
'"Sexe":1,"Simple":{"F":"","G":[],"H":{"H1":0,"H2":"","H3":{"H3a":false,"H3b":null}},"I":"","J":['+
|
||||
'{"J1":1,"J2":"","J3":"reLast"}]}}';
|
||||
assert(people.FromJSON(s));
|
||||
assert(people.ID=10);
|
||||
assert(people.FirstName='ab"c');
|
||||
assert(people.LastName='def');
|
||||
assert(people.YearOfBirth=20);
|
||||
assert(people.YearOfDeath=30);
|
||||
assert(people.Sexe=sMale);
|
||||
assert(people.Simple.J.Count=1);
|
||||
assert(people.Simple.J[0].J1=1);
|
||||
assert(people.Simple.J[0].J3=reLast);
|
||||
writeln('Connecting to the server at '+ServerAddress.Text+':888');
|
||||
GetClient(ServerAddress.Text,LogonName.Text,LogonPassword.Text,
|
||||
lambda(client)
|
||||
client.LogToRemoteServer(LOG_VERBOSE,'localhost');
|
||||
writeln('Safely connected with SessionID='+IntToStr(client.Authentication.SessionID));
|
||||
people := TSQLRecordPeople.Create(client,1);
|
||||
assert(people.ID=1);
|
||||
writeln(people.ToJSON(client.Model,'*'));
|
||||
writeln('Testing remote CRUD methods');
|
||||
ORMTest(client);
|
||||
BrowserAPI.console.timeEnd('ORM');
|
||||
BrowserAPI.console.time('SOA');
|
||||
writeln('Testing SOA remote access');
|
||||
SOATest(client,
|
||||
lambda
|
||||
writeln('Disconnect from server');
|
||||
client.Free;
|
||||
BrowserAPI.console.timeEnd('SOA');
|
||||
end,
|
||||
lambda
|
||||
writeln('ERROR!');
|
||||
writeln('Disconnect from server');
|
||||
client.Free;
|
||||
BrowserAPI.console.timeEnd('SOA');
|
||||
end);
|
||||
end,
|
||||
lambda
|
||||
ShowMessage('Impossible to connect to the server');
|
||||
writeln('ERROR at GetClient');
|
||||
BrowserAPI.console.timeEnd('ORM');
|
||||
end);
|
||||
end;
|
||||
|
||||
procedure TLoginForm.W3Button1Click(Sender: TObject);
|
||||
begin
|
||||
BrowserAPI.console.time('LowLevel');
|
||||
TestSMS;
|
||||
BrowserAPI.console.timeEnd('LowLevel');
|
||||
end;
|
||||
|
||||
procedure TLoginForm.Resize;
|
||||
begin
|
||||
inherited;
|
||||
end;
|
||||
|
||||
end.
|
@@ -0,0 +1,109 @@
|
||||
<SMART>
|
||||
<Form version="2" subversion="1">
|
||||
<Created>2014-06-17T10:47:09.864</Created>
|
||||
<Modified>2014-07-18T15:32:06.707</Modified>
|
||||
<object type="TW3Form">
|
||||
<Caption>mORMot Web Test</Caption>
|
||||
<Name>LoginForm</Name>
|
||||
<object type="TW3Label">
|
||||
<Caption><b><i>mORMot</i> Web Test</b></Caption>
|
||||
<Width>184</Width>
|
||||
<Top>8</Top>
|
||||
<StyleClass>h1</StyleClass>
|
||||
<Left>32</Left>
|
||||
<Height>32</Height>
|
||||
<Transparent>True</Transparent>
|
||||
<Name>W3Label1</Name>
|
||||
</object>
|
||||
<object type="TW3Panel">
|
||||
<Width>192</Width>
|
||||
<Top>40</Top>
|
||||
<Left>24</Left>
|
||||
<Height>264</Height>
|
||||
<Name>W3Panel1</Name>
|
||||
<object type="TW3EditBox">
|
||||
<Value></Value>
|
||||
<Text>User</Text>
|
||||
<Range></Range>
|
||||
<Width>128</Width>
|
||||
<Top>104</Top>
|
||||
<Left>16</Left>
|
||||
<Height>32</Height>
|
||||
<Name>LogonName</Name>
|
||||
</object>
|
||||
<object type="TW3Label">
|
||||
<Caption>Name</Caption>
|
||||
<Width>56</Width>
|
||||
<Top>80</Top>
|
||||
<Left>16</Left>
|
||||
<Height>24</Height>
|
||||
<Name>W3Label3</Name>
|
||||
</object>
|
||||
<object type="TW3Label">
|
||||
<Caption>Password</Caption>
|
||||
<Width>128</Width>
|
||||
<Top>136</Top>
|
||||
<Left>16</Left>
|
||||
<Height>32</Height>
|
||||
<Name>W3Label4</Name>
|
||||
</object>
|
||||
<object type="TW3EditBox">
|
||||
<Value></Value>
|
||||
<Text>synopse</Text>
|
||||
<Range></Range>
|
||||
<Width>128</Width>
|
||||
<Top>168</Top>
|
||||
<Left>16</Left>
|
||||
<Height>32</Height>
|
||||
<Name>LogonPassword</Name>
|
||||
</object>
|
||||
<object type="TW3Button">
|
||||
<Caption>Remote Tests</Caption>
|
||||
<Width>160</Width>
|
||||
<Top>208</Top>
|
||||
<Left>16</Left>
|
||||
<Height>40</Height>
|
||||
<Name>Connect</Name>
|
||||
<OnClick>ConnectClick</OnClick>
|
||||
</object>
|
||||
<object type="TW3EditBox">
|
||||
<Value></Value>
|
||||
<Text>127.0.0.1</Text>
|
||||
<Range></Range>
|
||||
<Width>128</Width>
|
||||
<Top>160</Top>
|
||||
<Left>240</Left>
|
||||
<Height>32</Height>
|
||||
<Name>W3EditBox1</Name>
|
||||
</object>
|
||||
<object type="TW3Label">
|
||||
<Caption>Server</Caption>
|
||||
<Width>128</Width>
|
||||
<Top>8</Top>
|
||||
<Left>16</Left>
|
||||
<Height>32</Height>
|
||||
<Name>W3Label2</Name>
|
||||
</object>
|
||||
<object type="TW3EditBox">
|
||||
<Value></Value>
|
||||
<Text>127.0.0.1</Text>
|
||||
<Range></Range>
|
||||
<Width>128</Width>
|
||||
<Top>40</Top>
|
||||
<Left>16</Left>
|
||||
<Height>32</Height>
|
||||
<Name>ServerAddress</Name>
|
||||
</object>
|
||||
</object>
|
||||
<object type="TW3Button">
|
||||
<Caption>Offline Tests</Caption>
|
||||
<Width>160</Width>
|
||||
<Top>312</Top>
|
||||
<Left>40</Left>
|
||||
<Height>40</Height>
|
||||
<Name>W3Button1</Name>
|
||||
<OnClick>W3Button1Click</OnClick>
|
||||
</object>
|
||||
</object>
|
||||
</Form>
|
||||
</SMART>
|
@@ -0,0 +1,36 @@
|
||||
unit MainUnit;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SmartCL.System, SmartCL.Components, SmartCL.Forms, SmartCL.Application,
|
||||
SynCrossPlatformCrypto, SynCrossPlatformSpecific, SynCrossPlatformREST,
|
||||
SmartTests,
|
||||
LoginForm;
|
||||
|
||||
type
|
||||
TApplication = class(TW3CustomApplication)
|
||||
private
|
||||
FForm1: TLoginForm;
|
||||
protected
|
||||
procedure ApplicationStarting; override;
|
||||
public
|
||||
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TApplication}
|
||||
|
||||
procedure TApplication.ApplicationStarting;
|
||||
begin
|
||||
FForm1 := TLoginForm.Create(Display.View);
|
||||
FForm1.Name := 'Form1';
|
||||
RegisterFormInstance(FForm1, True);
|
||||
// register other forms here
|
||||
|
||||
inherited;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
@@ -0,0 +1,31 @@
|
||||
SmartMobileStudio Client to mORMot
|
||||
==================================
|
||||
|
||||
Please ensure you first copied the latest version of those files
|
||||
from CrossPlatform folder into the SMS shared library folder, i.e.
|
||||
c:\ProgramData\Optimale Systemer AS\Smart Mobile Studio\Libraries\
|
||||
|
||||
- SynCrossPlatformCrypto.pas
|
||||
- SynCrossPlatformRest.pas
|
||||
- SynCrossPlatformSpecific.pas
|
||||
|
||||
For this, simply run CopySynCrossPlatformUnits.bat
|
||||
|
||||
Those units are needed as external content, to compile the
|
||||
demo application.
|
||||
|
||||
As an alternative, you may copy those units to the projects root
|
||||
folder, but you forget to synchronize the units from the official
|
||||
source code repository later.
|
||||
|
||||
### Server Needed
|
||||
|
||||
In order to let this client sample application run as exepected,
|
||||
you need to compile and run the RegressionTestsServer.dpr program,
|
||||
as available in "27 - CrossPlatform Clients" folder.
|
||||
|
||||
This server will publish TSQLRecordPeople remote ORM access,
|
||||
with TSQLRestServerAuthenticationDefault authentication.
|
||||
|
||||
|
||||
|
@@ -0,0 +1,271 @@
|
||||
unit SmartTests;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SmartCL.System,
|
||||
System.Types,
|
||||
ECMA.Date,
|
||||
System.Date,
|
||||
SynCrossPlatformSpecific,
|
||||
SynCrossPlatformREST,
|
||||
SynCrossPlatformCrypto;
|
||||
|
||||
procedure TestSMS;
|
||||
|
||||
procedure ORMTest(client: TSQLRestClientURI);
|
||||
|
||||
procedure SOATest(client: TSQLRestClientURI; onSuccess, onError: TSQLRestEvent);
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
mORMotClient; // unit generated by the server!
|
||||
|
||||
const
|
||||
MSecsPerDay = 86400000;
|
||||
OneSecDateTime = 1/SecsPerDay;
|
||||
|
||||
procedure TestsIso8601DateTime;
|
||||
procedure Test(D: TDateTime);
|
||||
var s: string;
|
||||
procedure One(D: TDateTime);
|
||||
var E: TDateTime;
|
||||
V: TTimeLog;
|
||||
J: JDate;
|
||||
begin
|
||||
J := new JDate;
|
||||
J.AsDateTime := D;
|
||||
E := J.AsDateTime;
|
||||
assert(Abs(D-E)<OneSecDateTime);
|
||||
s := DateTimeToIso8601(D);
|
||||
E := Iso8601ToDateTime(s);
|
||||
assert(Abs(D-E)<OneSecDateTime);
|
||||
V := DateTimeToTTimeLog(D);
|
||||
E := TTimeLogToDateTime(V);
|
||||
assert(Abs(D-E)<OneSecDateTime);
|
||||
assert(UrlDecode(UrlEncode(s))=s);
|
||||
end;
|
||||
begin
|
||||
One(D);
|
||||
assert(length(s)=19);
|
||||
One(Trunc(D));
|
||||
assert(length(s)=10);
|
||||
One(Frac(D));
|
||||
assert(length(s)=9);
|
||||
end;
|
||||
var D: TDateTime;
|
||||
i: integer;
|
||||
s,x: string;
|
||||
T: TTimeLog;
|
||||
begin
|
||||
s := '2014-06-28T11:50:22';
|
||||
D := Iso8601ToDateTime(s);
|
||||
assert(DateTimeToIso8601(D)=s);
|
||||
assert(Abs(D-41818.40997685185)<OneSecDateTime);
|
||||
x := TTimeLogToIso8601(135181810838);
|
||||
assert(x=s);
|
||||
T := DateTimeToTTimeLog(D);
|
||||
assert(T=135181810838);
|
||||
D := Now/20+Random*20; // some starting random date/time
|
||||
for i := 1 to 2000 do begin
|
||||
Test(D);
|
||||
D := D+Random*57; // go further a little bit: change date/time
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TestSMS;
|
||||
var doc: TJSONVariantData;
|
||||
begin
|
||||
assert(crc32ascii(0,'abcdefghijklmnop')=$943AC093);
|
||||
assert(SHA256('abc')='ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad');
|
||||
assert(VariantType(123)=jvUndefined);
|
||||
assert(VariantType(null)=jvUndefined);
|
||||
assert(VariantType(TVariant.CreateObject)=jvObject);
|
||||
assert(VariantType(new JObject)=jvObject);
|
||||
assert(VariantType(TVariant.CreateArray)=jvArray);
|
||||
doc := TJSONVariantData.Create('{"a":1,"b":"B"}');
|
||||
assert(doc.Kind=jvObject);
|
||||
assert(doc.Count=2);
|
||||
assert(doc.Names[0]='a');
|
||||
assert(doc.Names[1]='b');
|
||||
assert(doc.Values[0]=1);
|
||||
assert(doc.Values[1]='B');
|
||||
doc := TJSONVariantData.Create('["a",2]');
|
||||
assert(doc.Kind=jvArray);
|
||||
assert(doc.Count=2);
|
||||
assert(doc.Names.Count=0);
|
||||
assert(doc.Values[0]='a');
|
||||
assert(doc.Values[1]=2);
|
||||
TestsIso8601DateTime;
|
||||
end;
|
||||
|
||||
|
||||
procedure ORMTest(client: TSQLRestClientURI);
|
||||
var people: TSQLRecordPeople;
|
||||
Call: TSQLRestURIParams;
|
||||
res: TIntegerDynArray;
|
||||
i,id: integer;
|
||||
begin // all this is run in synchronous mode -> only 200 records in the set
|
||||
client.CallBackGet('DropTable',[],Call,TSQLRecordPeople);
|
||||
assert(client.InternalState>0);
|
||||
assert(Call.OutStatus=HTTP_SUCCESS);
|
||||
client.BatchStart(TSQLRecordPeople);
|
||||
people := TSQLRecordPeople.Create;
|
||||
assert(people.InternalState=0);
|
||||
for i := 1 to 200 do begin
|
||||
people.FirstName := 'First'+IntToStr(i);
|
||||
people.LastName := 'Last'+IntToStr(i);
|
||||
people.YearOfBirth := i+1800;
|
||||
people.YearOfDeath := i+1825;
|
||||
assert(client.BatchAdd(people,true)=i-1);
|
||||
assert(people.InternalState=0);
|
||||
end;
|
||||
assert(client.BatchSend(res)=HTTP_SUCCESS);
|
||||
assert(length(res)=200);
|
||||
for i := 1 to 200 do
|
||||
assert(res[i-1]=i);
|
||||
people := TSQLRecordPeople.CreateAndFillPrepare(client,'','',[]);
|
||||
assert(people.InternalState=0);
|
||||
id := 0;
|
||||
while people.FillOne do begin
|
||||
assert(people.InternalState=client.InternalState);
|
||||
inc(id);
|
||||
assert(people.ID=id);
|
||||
assert(people.FirstName='First'+IntToStr(id));
|
||||
assert(people.LastName='Last'+IntToStr(id));
|
||||
assert(people.YearOfBirth=id+1800);
|
||||
assert(people.YearOfDeath=id+1825);
|
||||
end;
|
||||
assert(id=200);
|
||||
people.Free; // release all memory used by the request
|
||||
people := TSQLRecordPeople.CreateAndFillPrepare(client,
|
||||
'YearOFBIRTH,Yearofdeath,id','',[]);
|
||||
assert(people.InternalState=0);
|
||||
id := 0;
|
||||
while people.FillOne do begin
|
||||
assert(people.InternalState=client.InternalState);
|
||||
inc(id);
|
||||
assert(people.ID=id);
|
||||
assert(people.FirstName='');
|
||||
assert(people.LastName='');
|
||||
assert(people.YearOfBirth=id+1800);
|
||||
assert(people.YearOfDeath=id+1825);
|
||||
end;
|
||||
assert(id=200);
|
||||
people.Free; // release all memory used by the request
|
||||
people := TSQLRecordPeople.CreateAndFillPrepare(client,'',
|
||||
'yearofbirth=?',[1900]);
|
||||
id := 0;
|
||||
while people.FillOne do begin
|
||||
assert(people.InternalState=client.InternalState);
|
||||
inc(id);
|
||||
assert(people.ID=100);
|
||||
assert(people.FirstName='First100');
|
||||
assert(people.LastName='Last100');
|
||||
assert(people.YearOfBirth=1900);
|
||||
assert(people.YearOfDeath=1925);
|
||||
end;
|
||||
assert(id=1);
|
||||
for i := 1 to 200 do
|
||||
if i and 15=0 then
|
||||
client.Delete(TSQLRecordPeople,i) else
|
||||
if i mod 82=0 then begin
|
||||
people := TSQLRecordPeople.Create;
|
||||
id := i+1;
|
||||
people.ID := i;
|
||||
people.FirstName := 'neversent';
|
||||
people.LastName := 'neitherthisone';
|
||||
people.YearOfBirth := id+1800;
|
||||
people.YearOfDeath := id+1825;
|
||||
assert(people.InternalState=0);
|
||||
assert(client.Update(people,'YEarOFBIRTH,YEarOfDeath'));
|
||||
assert(people.InternalState=client.InternalState);
|
||||
end;
|
||||
people := new TSQLRecordPeople;
|
||||
assert(people.InternalState=0);
|
||||
for i := 1 to 200 do begin
|
||||
var read = client.Retrieve(i,people);
|
||||
if i and 15=0 then
|
||||
assert(not read) else begin
|
||||
assert(read);
|
||||
assert(people.InternalState=client.InternalState);
|
||||
if i mod 82=0 then
|
||||
id := i+1 else
|
||||
id := i;
|
||||
assert(people.ID=i);
|
||||
assert(people.FirstName='First'+IntToStr(i));
|
||||
assert(people.LastName='Last'+IntToStr(i));
|
||||
assert(people.YearOfBirth=id+1800);
|
||||
assert(people.YearOfDeath=id+1825);
|
||||
end;
|
||||
end;
|
||||
people.Free;
|
||||
end;
|
||||
|
||||
procedure SOATest(client: TSQLRestClientURI; onSuccess, onError: TSQLRestEvent);
|
||||
var Calc: TServiceCalculator;
|
||||
i: integer;
|
||||
const SEX_TEXT: array[0..1] of string = ('Miss','Mister');
|
||||
ITERATIONS = 50;
|
||||
begin
|
||||
Calc := TServiceCalculator.Create(client); // no need to free instance on SMS
|
||||
assert(Calc.InstanceImplementation=sicShared);
|
||||
assert(Calc.ServiceName='Calculator');
|
||||
// first test synchronous / blocking mode
|
||||
for i := 1 to ITERATIONS do
|
||||
assert(calc._Add(i,i+1)=i*2+1);
|
||||
for i := 1 to ITERATIONS do begin
|
||||
var sex := TPeopleSexe(i and 1);
|
||||
var name := 'Smith';
|
||||
calc._ToText(i,'$',sex,name);
|
||||
assert(sex=sFemale);
|
||||
assert(name=format('$ %d for %s Smith',[i,SEX_TEXT[i and 1]]));
|
||||
end;
|
||||
var j: integer;
|
||||
var rec: TTestCustomJSONArraySimpleArray;
|
||||
for i := 1 to ITERATIONS do begin
|
||||
var name := calc._RecordToText(rec);
|
||||
if i=1 then
|
||||
assert(name='{"F":"","G":[],"H":{"H1":0,"H2":"","H3":{"H3a":false,"H3b":null}},"I":"","J":[]}');
|
||||
assert(length(Rec.F)=i);
|
||||
for j := 1 to length(Rec.F) do
|
||||
assert(Rec.F[j]='!');
|
||||
assert(length(Rec.G)=i);
|
||||
for j := 0 to high(Rec.G) do
|
||||
assert(Rec.G[j]=IntToStr(j+1));
|
||||
assert(Rec.H.H1=i);
|
||||
assert(length(Rec.J)=i-1);
|
||||
for j := 0 to high(Rec.J) do begin
|
||||
assert(Rec.J[j].J1=j);
|
||||
assert(Rec.J[j].J2<>'');
|
||||
assert(Rec.J[j].J3=TRecordEnum(j mod (ord(high(TRecordEnum))+1)));
|
||||
end;
|
||||
end;
|
||||
// code below is asynchronous, so more difficult to follow than synchronous !
|
||||
i := 1; // need two Calc*Asynch() inlined lambdas to access var i
|
||||
procedure CalcToTextAsynch(sexe: TPeopleSexe; name: string);
|
||||
begin
|
||||
assert(sexe=sFemale);
|
||||
assert(name=format('$ %d for %s Smith',[i,SEX_TEXT[i and 1]]));
|
||||
inc(i);
|
||||
sexe := TPeopleSexe(i and 1);
|
||||
name := 'Smith';
|
||||
if i<=ITERATIONS then // recursive for i := 1 to ITERATIONS
|
||||
Calc.ToText(i,'$',sexe,name,CalcToTextAsynch,onError) else
|
||||
onSuccess(client);
|
||||
end;
|
||||
procedure CalcAddAsynch(res: integer);
|
||||
begin
|
||||
assert(res=i*2+1);
|
||||
inc(i);
|
||||
if i<=ITERATIONS then // recursive for i := 1 to ITERATIONS
|
||||
Calc.Add(i,i+1,CalcAddAsynch,onError) else begin
|
||||
i := 1;
|
||||
Calc.ToText(i,'$',TPeopleSexe(i and 1),'Smith',CalcToTextAsynch,onError);
|
||||
end;
|
||||
end;
|
||||
Calc.Add(i,i+1,CalcAddAsynch,onError);
|
||||
end;
|
||||
|
||||
end.
|
@@ -0,0 +1,125 @@
|
||||
<SMART>
|
||||
<Project version="2" subversion="2">
|
||||
<Name>WebForm</Name>
|
||||
<Created>T00:00:00.000</Created>
|
||||
<Modified>2016-07-27T16:44:14.890</Modified>
|
||||
<Author>A. Bouchez</Author>
|
||||
<Company>Synopse</Company>
|
||||
<Version>
|
||||
<Major>1</Major>
|
||||
<Minor>18</Minor>
|
||||
<Revision>0</Revision>
|
||||
</Version>
|
||||
<VendorSpecific>
|
||||
<Apple>
|
||||
<FormatDetection>0</FormatDetection>
|
||||
<StatusBarStyle>default</StatusBarStyle>
|
||||
<WebAppCapable>1</WebAppCapable>
|
||||
</Apple>
|
||||
<ChromeApp>
|
||||
<Kiosk>0</Kiosk>
|
||||
<KioskOnly>1</KioskOnly>
|
||||
<OfflineEnabled>1</OfflineEnabled>
|
||||
</ChromeApp>
|
||||
<Cordova>
|
||||
<WidgetID>com.smartmobilestudio.app</WidgetID>
|
||||
<AllowIntent>http://*/* https://*/* tel:* sms:* mailto:* geo:*</AllowIntent>
|
||||
</Cordova>
|
||||
</VendorSpecific>
|
||||
<Options>
|
||||
<PostBuild>
|
||||
<Enabled>0</Enabled>
|
||||
<Script>//CopyFile('.\www\index.html','.\www\debug\index.html',true);</Script>
|
||||
</PostBuild>
|
||||
<Compiler>
|
||||
<Assertions>1</Assertions>
|
||||
<Optimize>1</Optimize>
|
||||
<HintsLevel>1</HintsLevel>
|
||||
</Compiler>
|
||||
<Codegen>
|
||||
<Obfuscation>0</Obfuscation>
|
||||
<RangeChecking>0</RangeChecking>
|
||||
<InstanceChecking>0</InstanceChecking>
|
||||
<ConditionChecking>1</ConditionChecking>
|
||||
<LoopChecking>1</LoopChecking>
|
||||
<InlineMagics>1</InlineMagics>
|
||||
<IgnorePublishedInImplementation>0</IgnorePublishedInImplementation>
|
||||
<EmitSourceLocation>1</EmitSourceLocation>
|
||||
<EmitRTTI>0</EmitRTTI>
|
||||
<Devirtualize>1</Devirtualize>
|
||||
<MainBody>1</MainBody>
|
||||
<CodePacking>0</CodePacking>
|
||||
<SmartLinking>1</SmartLinking>
|
||||
<Verbosity>1</Verbosity>
|
||||
</Codegen>
|
||||
<ConditionalDefines>
|
||||
<HandleExceptions>1</HandleExceptions>
|
||||
<AutoRefresh>0</AutoRefresh>
|
||||
<LegacySupportForIE>0</LegacySupportForIE>
|
||||
</ConditionalDefines>
|
||||
<Linker>
|
||||
<SourceMap>0</SourceMap>
|
||||
<CompressCSS>1</CompressCSS>
|
||||
<GenerateAppCacheManifest>1</GenerateAppCacheManifest>
|
||||
<GenerateChromeAppManifest>0</GenerateChromeAppManifest>
|
||||
<GenerateFireFoxManifest>0</GenerateFireFoxManifest>
|
||||
<GenerateWebAppManifest>1</GenerateWebAppManifest>
|
||||
<GenerateWidgetPackageConfigXML>0</GenerateWidgetPackageConfigXML>
|
||||
<GenerateCordovaConfigXML>1</GenerateCordovaConfigXML>
|
||||
<ExternalCSS>0</ExternalCSS>
|
||||
<Theme>default.css</Theme>
|
||||
<CustomTheme>0</CustomTheme>
|
||||
<EmbedJavaScript>1</EmbedJavaScript>
|
||||
</Linker>
|
||||
<Output>
|
||||
<HtmlFileName>index.html</HtmlFileName>
|
||||
<OutputFilePath>www\</OutputFilePath>
|
||||
</Output>
|
||||
<Import />
|
||||
<Execute>
|
||||
<ServeManifest>0</ServeManifest>
|
||||
<Server>1</Server>
|
||||
<CustomFile></CustomFile>
|
||||
<LoadCustomFile>0</LoadCustomFile>
|
||||
<PauseAfterExecution>0</PauseAfterExecution>
|
||||
<ExecuteType>1</ExecuteType>
|
||||
<ExecuteableParams>%output%</ExecuteableParams>
|
||||
</Execute>
|
||||
</Options>
|
||||
<Files>
|
||||
<File type="main">
|
||||
<Name>WebForm</Name>
|
||||
<Created>2014-07-11T23:12:17.628Z</Created>
|
||||
<Modified>2014-07-11T23:12:17.629</Modified>
|
||||
<Filename>WebForm.pas</Filename>
|
||||
</File>
|
||||
<File type="unit">
|
||||
<Name>MainUnit</Name>
|
||||
<Created>2014-06-17T10:47:09.813Z</Created>
|
||||
<Modified>2014-07-11T23:12:17.619</Modified>
|
||||
<Filename>MainUnit.pas</Filename>
|
||||
</File>
|
||||
<File type="form">
|
||||
<Name>LoginForm</Name>
|
||||
<Created>2014-06-17T10:47:09.813Z</Created>
|
||||
<Modified>2014-09-08T18:00:47.737</Modified>
|
||||
<Filename>LoginForm.pas</Filename>
|
||||
<AutoCreate>
|
||||
<IsAutoCreate>1</IsAutoCreate>
|
||||
<IsMainForm>1</IsMainForm>
|
||||
<Order>1</Order>
|
||||
</AutoCreate>
|
||||
</File>
|
||||
</Files>
|
||||
<Target>Browser</Target>
|
||||
<Generator>Visual Component Project</Generator>
|
||||
<Statistics>
|
||||
<BackgroundCompilations>36</BackgroundCompilations>
|
||||
<EditTime>00:03:35.206</EditTime>
|
||||
<CompileTime>00:00:34.311</CompileTime>
|
||||
<TotalTime>01:24:55.433</TotalTime>
|
||||
<DesigningTime>00:04:05.595</DesigningTime>
|
||||
<RunningTime>00:44:02.193</RunningTime>
|
||||
</Statistics>
|
||||
</Project>
|
||||
</SMART>
|
@@ -0,0 +1,26 @@
|
||||
uses MainUnit;
|
||||
|
||||
{$IFDEF SMART_INTERNAL_HANDLE_EXCEPTIONS}
|
||||
uses W3System;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF SMART_INTERNAL_AUTO_REFRESH}
|
||||
uses W3AutoRefresh;
|
||||
TW3AutoRefresh.Create.Start;
|
||||
{$ENDIF}
|
||||
|
||||
var Application: TApplication;
|
||||
|
||||
{$IFDEF SMART_INTERNAL_HANDLE_EXCEPTIONS}
|
||||
try
|
||||
{$ENDIF}
|
||||
|
||||
Application := TApplication.Create;
|
||||
Application.RunApp;
|
||||
|
||||
{$IFDEF SMART_INTERNAL_HANDLE_EXCEPTIONS}
|
||||
except
|
||||
on e: Exception do
|
||||
ShowMessage(e.Message);
|
||||
end;
|
||||
{$ENDIF}
|
@@ -0,0 +1,436 @@
|
||||
/// remote access to a mORMot server using SmartMobileStudio
|
||||
// - retrieved from http://localhost:888/root/wrapper/SmartMobileStudio/mORMotClient.pas
|
||||
// at 2014-12-10 21:44:23 using "SmartMobileStudio.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 Smart Mobile Studio 2.1.1 and later.
|
||||
}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SmartCL.System,
|
||||
System.Types,
|
||||
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;
|
||||
// those overriden methods will emulate the needed RTTI
|
||||
class function ComputeRTTI: TRTTIPropInfos; override;
|
||||
procedure SetProperty(FieldIndex: integer; const Value: variant); override;
|
||||
function GetProperty(FieldIndex: integer): variant; override;
|
||||
public
|
||||
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;
|
||||
property Simple: TTestCustomJSONArraySimpleArray read fSimple write fSimple;
|
||||
end;
|
||||
|
||||
/// service accessible via http://localhost:888/root/Calculator
|
||||
// - this service will run in sicShared mode
|
||||
// - synchronous and asynchronous methods are available, depending on use case
|
||||
// - synchronous _*() methods will block the browser execution, so won't be
|
||||
// appropriate for long process - on error, they may raise EServiceException
|
||||
TServiceCalculator = class(TServiceClientAbstract)
|
||||
public
|
||||
/// will initialize an access to the remote service
|
||||
constructor Create(aClient: TSQLRestClientURI); override;
|
||||
|
||||
procedure Add(n1: Integer; n2: Integer;
|
||||
onSuccess: procedure(Result: Integer); onError: TSQLRestEvent);
|
||||
function _Add(const n1: Integer; const n2: Integer): Integer;
|
||||
|
||||
procedure ToText(Value: Currency; Curr: String; Sexe: TPeopleSexe; Name: String;
|
||||
onSuccess: procedure(Sexe: TPeopleSexe; Name: String); onError: TSQLRestEvent);
|
||||
procedure _ToText(const Value: Currency; const Curr: RawUTF8; var Sexe: TPeopleSexe; var Name: RawUTF8);
|
||||
|
||||
procedure RecordToText(Rec: TTestCustomJSONArraySimpleArray;
|
||||
onSuccess: procedure(Rec: TTestCustomJSONArraySimpleArray; Result: String); onError: TSQLRestEvent);
|
||||
function _RecordToText(var Rec: TTestCustomJSONArraySimpleArray): String;
|
||||
|
||||
procedure GetPeople(id: TID; arr: TSimpleRecordDynArray;
|
||||
onSuccess: procedure(People: TSQLRecordPeople; Sexes: TPeopleSexeDynArray; arr: TSimpleRecordDynArray; Result: Boolean); onError: TSQLRestEvent);
|
||||
function _GetPeople(const id: TID; var People: TSQLRecordPeople; var 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
|
||||
// - request will be asynchronous, and trigger onSuccess or onError event
|
||||
procedure GetClient(const aServerAddress, aUserName,aPassword: string;
|
||||
onSuccess, onError: TSQLRestEvent; aServerPort: integer=SERVER_PORT);
|
||||
|
||||
// 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(const Value: variant): TTestCustomJSONArraySimpleArray;
|
||||
function TTestCustomJSONArraySimpleArray2Variant(const Value: TTestCustomJSONArraySimpleArray): variant;
|
||||
function Variant2TSimpleRecord(const Value: variant): TSimpleRecord;
|
||||
function TSimpleRecord2Variant(const Value: 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 }
|
||||
|
||||
{$HINTS OFF} // for begin asm return ... end; end below
|
||||
|
||||
// those functions will use the existing generated string array constant
|
||||
// defined by the SMS compiler for each enumeration
|
||||
|
||||
function Variant2TPeopleSexe(const _variant: variant): TPeopleSexe;
|
||||
begin
|
||||
asm return @VariantToEnum(@_variant,@TPeopleSexe); end;
|
||||
end;
|
||||
|
||||
function Variant2TRecordEnum(const _variant: variant): TRecordEnum;
|
||||
begin
|
||||
asm return @VariantToEnum(@_variant,@TRecordEnum); end;
|
||||
end;
|
||||
|
||||
{$HINTS ON}
|
||||
|
||||
{ Some helpers for record types:
|
||||
due to potential obfuscation of generated JavaScript, we can't assume
|
||||
that the JSON used for transmission would match record fields naming }
|
||||
|
||||
function Variant2TTestCustomJSONArraySimpleArray(const Value: variant): TTestCustomJSONArraySimpleArray;
|
||||
begin
|
||||
result.F := Value.F;
|
||||
if VariantType(Value.G)=jvArray then
|
||||
for var i := 0 to integer(Value.G.length)-1 do
|
||||
result.G.Add(String(Value.G[i]));
|
||||
result.H.H1 := Value.H.H1;
|
||||
result.H.H2 := Value.H.H2;
|
||||
result.H.H3.H3a := Value.H.H3.H3a;
|
||||
result.H.H3.H3b := VariantToBlob(Value.H.H3.H3b);
|
||||
result.I := Iso8601ToDateTime(Value.I);
|
||||
if VariantType(Value.J)=jvArray then begin
|
||||
var tmp: TTestCustomJSONArraySimpleArray;
|
||||
tmp.J.SetLength(1);
|
||||
for var n := 0 to integer(Value.J.length)-1 do begin
|
||||
var source := Value.J[n];
|
||||
var dest := tmp.J[0];
|
||||
dest.J1 := source.J1;
|
||||
dest.J2 := VariantToGUID(source.J2);
|
||||
dest.J3 := Variant2TRecordEnum(source.J3);
|
||||
result.J.Add(dest);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTestCustomJSONArraySimpleArray2Variant(const Value: TTestCustomJSONArraySimpleArray): variant;
|
||||
begin
|
||||
result := new JObject;
|
||||
result.F := Value.F;
|
||||
result.G := variant(Value.G);
|
||||
result.H := new JObject;
|
||||
result.H.H1 := Value.H.H1;
|
||||
result.H.H2 := Value.H.H2;
|
||||
result.H.H3 := new JObject;
|
||||
result.H.H3.H3a := Value.H.H3.H3a;
|
||||
result.H.H3.H3b := BlobToVariant(Value.H.H3.H3b);
|
||||
result.I := DateTimeToIso8601(Value.I);
|
||||
result.J := TVariant.CreateArray;
|
||||
for var source in Value.J do begin
|
||||
var dest: variant := new JObject;
|
||||
dest.J1 := source.J1;
|
||||
dest.J2 := GUIDToVariant(source.J2);
|
||||
dest.J3 := ord(source.J3);
|
||||
result.J.push(dest);
|
||||
end;
|
||||
end;
|
||||
|
||||
function Variant2TSimpleRecord(const Value: variant): TSimpleRecord;
|
||||
begin
|
||||
result.A := Value.A;
|
||||
result.B := Value.B;
|
||||
result.C := Value.C;
|
||||
end;
|
||||
|
||||
function TSimpleRecord2Variant(const Value: TSimpleRecord): variant;
|
||||
begin
|
||||
result := new JObject;
|
||||
result.A := Value.A;
|
||||
result.B := Value.B;
|
||||
result.C := Value.C;
|
||||
end;
|
||||
|
||||
|
||||
{ Some helpers for dynamic array types }
|
||||
|
||||
function Variant2TPeopleSexeDynArray(const _variant: variant): TPeopleSexeDynArray;
|
||||
var tmp: Byte;
|
||||
begin
|
||||
if VariantType(_variant)=jvArray then
|
||||
for var i := 0 to integer(_variant.Length)-1 do begin
|
||||
tmp := (_variant[i]);
|
||||
result.Add(tmp);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPeopleSexeDynArray2Variant(const _array: TPeopleSexeDynArray): variant;
|
||||
var i: integer;
|
||||
begin
|
||||
result := TVariant.CreateArray;
|
||||
for i := 0 to high(_array) do
|
||||
result.push((_array[i]));
|
||||
end;
|
||||
|
||||
function Variant2TSimpleRecordDynArray(const _variant: variant): TSimpleRecordDynArray;
|
||||
var tmp: TSimpleRecord;
|
||||
begin
|
||||
if VariantType(_variant)=jvArray then
|
||||
for var i := 0 to integer(_variant.Length)-1 do begin
|
||||
tmp := Variant2TSimpleRecord(_variant[i]);
|
||||
result.Add(tmp);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSimpleRecordDynArray2Variant(const _array: TSimpleRecordDynArray): variant;
|
||||
var i: integer;
|
||||
begin
|
||||
result := TVariant.CreateArray;
|
||||
for i := 0 to high(_array) do
|
||||
result.push(TSimpleRecord2Variant(_array[i]));
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ TSQLRecordPeople }
|
||||
|
||||
class function TSQLRecordPeople.ComputeRTTI: TRTTIPropInfos;
|
||||
begin
|
||||
result := TRTTIPropInfos.Create(
|
||||
['FirstName','LastName','Data','YearOfBirth','YearOfDeath','Sexe','Simple'],
|
||||
[sftUnspecified,sftUnspecified,sftBlob,sftUnspecified,sftUnspecified,sftUnspecified,sftRecord]);
|
||||
end;
|
||||
|
||||
procedure TSQLRecordPeople.SetProperty(FieldIndex: integer; const Value: variant);
|
||||
begin
|
||||
case FieldIndex of
|
||||
0: fID := Value;
|
||||
1: fFirstName := Value;
|
||||
2: fLastName := Value;
|
||||
3: fData := VariantToBlob(Value);
|
||||
4: fYearOfBirth := Value;
|
||||
5: fYearOfDeath := Value;
|
||||
6: fSexe := Variant2TPeopleSexe(Value);
|
||||
7: fSimple := Variant2TTestCustomJSONArraySimpleArray(Value);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSQLRecordPeople.GetProperty(FieldIndex: integer): variant;
|
||||
begin
|
||||
case FieldIndex of
|
||||
0: result := fID;
|
||||
1: result := fFirstName;
|
||||
2: result := fLastName;
|
||||
3: result := BlobToVariant(fData);
|
||||
4: result := fYearOfBirth;
|
||||
5: result := fYearOfDeath;
|
||||
6: result := ord(fSexe);
|
||||
7: result := TTestCustomJSONArraySimpleArray2Variant(fSimple);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function GetModel: TSQLModel;
|
||||
begin
|
||||
result := TSQLModel.Create([TSQLAuthUser,TSQLAuthGroup,TSQLRecordPeople],'root');
|
||||
end;
|
||||
|
||||
procedure GetClient(const aServerAddress, aUserName,aPassword: string;
|
||||
onSuccess, onError: TSQLRestEvent; aServerPort: integer);
|
||||
begin
|
||||
var client := TSQLRestClientHTTP.Create(aServerAddress,aServerPort,GetModel,true);
|
||||
client.Connect(
|
||||
lambda
|
||||
try
|
||||
if client.ServerTimeStamp=0 then begin
|
||||
if Assigned(onError) then
|
||||
onError(client);
|
||||
exit;
|
||||
end;
|
||||
if not client.SetUser(TSQLRestServerAuthenticationDefault,aUserName,aPassword) then begin
|
||||
if Assigned(onError) then
|
||||
onError(client);
|
||||
exit;
|
||||
end;
|
||||
if Assigned(onSuccess) then
|
||||
onSuccess(client);
|
||||
except
|
||||
if Assigned(onError) then
|
||||
onError(client);
|
||||
end;
|
||||
end,
|
||||
onError);
|
||||
end;
|
||||
|
||||
|
||||
{ TServiceCalculator }
|
||||
|
||||
constructor TServiceCalculator.Create(aClient: TSQLRestClientURI);
|
||||
begin
|
||||
fServiceName := 'Calculator';
|
||||
fServiceURI := 'Calculator';
|
||||
fInstanceImplementation := sicShared;
|
||||
fContractExpected := '814F1362B19B2F4D';
|
||||
inherited Create(aClient);
|
||||
end;
|
||||
|
||||
|
||||
procedure TServiceCalculator.Add(n1: Integer; n2: Integer;
|
||||
onSuccess: procedure(Result: Integer); onError: TSQLRestEvent);
|
||||
begin
|
||||
fClient.CallRemoteServiceAsynch(self,'Add',1,
|
||||
[n1,n2],
|
||||
lambda (res: array of Variant)
|
||||
onSuccess(res[0]);
|
||||
end, onError);
|
||||
end;
|
||||
|
||||
function TServiceCalculator._Add(const n1: Integer; const n2: Integer): Integer;
|
||||
begin
|
||||
var res := fClient.CallRemoteServiceSynch(self,'Add',1,
|
||||
[n1,n2]);
|
||||
Result := res[0];
|
||||
end;
|
||||
|
||||
|
||||
procedure TServiceCalculator.ToText(Value: Currency; Curr: String; Sexe: TPeopleSexe; Name: String;
|
||||
onSuccess: procedure(Sexe: TPeopleSexe; Name: String); onError: TSQLRestEvent);
|
||||
begin
|
||||
fClient.CallRemoteServiceAsynch(self,'ToText',2,
|
||||
[Value,Curr,ord(Sexe),Name],
|
||||
lambda (res: array of Variant)
|
||||
onSuccess(Variant2TPeopleSexe(res[0]),res[1]);
|
||||
end, onError);
|
||||
end;
|
||||
|
||||
procedure TServiceCalculator._ToText(const Value: Currency; const Curr: RawUTF8; var Sexe: TPeopleSexe; var Name: RawUTF8);
|
||||
begin
|
||||
var res := fClient.CallRemoteServiceSynch(self,'ToText',2,
|
||||
[Value,Curr,ord(Sexe),Name]);
|
||||
Sexe := Variant2TPeopleSexe(res[0]);
|
||||
Name := res[1];
|
||||
end;
|
||||
|
||||
|
||||
procedure TServiceCalculator.RecordToText(Rec: TTestCustomJSONArraySimpleArray;
|
||||
onSuccess: procedure(Rec: TTestCustomJSONArraySimpleArray; Result: String); onError: TSQLRestEvent);
|
||||
begin
|
||||
fClient.CallRemoteServiceAsynch(self,'RecordToText',2,
|
||||
[TTestCustomJSONArraySimpleArray2Variant(Rec)],
|
||||
lambda (res: array of Variant)
|
||||
onSuccess(Variant2TTestCustomJSONArraySimpleArray(res[0]),res[1]);
|
||||
end, onError);
|
||||
end;
|
||||
|
||||
function TServiceCalculator._RecordToText(var Rec: TTestCustomJSONArraySimpleArray): String;
|
||||
begin
|
||||
var res := fClient.CallRemoteServiceSynch(self,'RecordToText',2,
|
||||
[TTestCustomJSONArraySimpleArray2Variant(Rec)]);
|
||||
Rec := Variant2TTestCustomJSONArraySimpleArray(res[0]);
|
||||
Result := res[1];
|
||||
end;
|
||||
|
||||
|
||||
procedure TServiceCalculator.GetPeople(id: TID; arr: TSimpleRecordDynArray;
|
||||
onSuccess: procedure(People: TSQLRecordPeople; Sexes: TPeopleSexeDynArray; arr: TSimpleRecordDynArray; Result: Boolean); onError: TSQLRestEvent);
|
||||
begin
|
||||
fClient.CallRemoteServiceAsynch(self,'GetPeople',4,
|
||||
[id,TSimpleRecordDynArray2Variant(arr)],
|
||||
lambda (res: array of Variant)
|
||||
onSuccess(TSQLRecordPeople.CreateFromVariant(res[0]),Variant2TPeopleSexeDynArray(res[1]),Variant2TSimpleRecordDynArray(res[2]),res[3]);
|
||||
end, onError);
|
||||
end;
|
||||
|
||||
function TServiceCalculator._GetPeople(const id: TID; var People: TSQLRecordPeople; var Sexes: TPeopleSexeDynArray; var arr: TSimpleRecordDynArray): Boolean;
|
||||
begin
|
||||
var res := fClient.CallRemoteServiceSynch(self,'GetPeople',4,
|
||||
[id,TSimpleRecordDynArray2Variant(arr)]);
|
||||
People := TSQLRecordPeople.CreateFromVariant(res[0]);
|
||||
Sexes := Variant2TPeopleSexeDynArray(res[1]);
|
||||
arr := Variant2TSimpleRecordDynArray(res[2]);
|
||||
Result := res[3];
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
Reference in New Issue
Block a user