309 lines
10 KiB
Plaintext
309 lines
10 KiB
Plaintext
/// remote access to a mORMot server using SynCrossPlatform* units
|
|
{{#uri}}
|
|
// - retrieved from {{protocol}}://{{host}}/{{uri}}
|
|
// at {{time}} using "{{templateName}}" template
|
|
{{/uri}}
|
|
{{^uri}}
|
|
// - generated at {{time}}
|
|
{{/uri}}
|
|
unit {{fileName}};
|
|
|
|
{
|
|
WARNING:
|
|
This unit has been generated by a mORMot {{mORMotVersion}} server.
|
|
Any manual modification of this file may be lost after regeneration.
|
|
|
|
Synopse mORMot framework. Copyright (C) {{year}} Arnaud Bouchez
|
|
Synopse Informatique - http://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;
|
|
|
|
{{! recursive partials used to write records type definition}}
|
|
{{<writerec}}record
|
|
{{#fields}}
|
|
{{nestedIdentation}} {{propName}}: {{#typePascal}}{{typePascal}};{{/typePascal}}{{#nestedRecord}}{{>writerec}}{{nestedIdentation}} end;{{/nestedRecord}}{{#nestedSimpleArray}}array of {{typePascal}};{{/nestedSimpleArray}}{{#nestedRecordArray}}array of {{>writerec}}{{nestedIdentation}} end;{{/nestedRecordArray}}
|
|
{{/fields}}{{/writerec}}
|
|
{{#withEnumerates}}
|
|
type // define some enumeration types, used below
|
|
{{#enumerates}}
|
|
{{name}} = ({{#values}}{{.}}{{^-last}}, {{/-last}}{{/values}});
|
|
{{/enumerates}}
|
|
|
|
{{/withEnumerates}}
|
|
{{#withSets}}
|
|
type // define some set types, used below
|
|
{{#sets}}
|
|
{{name}} = set of({{#values}}{{.}}{{^-last}}, {{/-last}}{{/values}});
|
|
{{/sets}}
|
|
|
|
{{/withSets}}
|
|
{{#withRecords}}
|
|
type // define some record types, used as properties below
|
|
{{#records}}
|
|
{{name}} = {{>writerec}} end;
|
|
|
|
{{/records}}
|
|
{{/withRecords}}
|
|
{{#withArrays}}
|
|
type // define some dynamic array types, used as properties below
|
|
{{#arrays}}
|
|
{{name}} = array of {{typeSource}};
|
|
{{/arrays}}
|
|
|
|
{{/withArrays}}
|
|
{{<method}}{{methodName}}({{#args}}{{^dirResult}}{{dirName}} {{argName}}: {{typePascal}}{{commaArg}}{{/dirResult}}{{/args}}){{#args}}{{#dirResult}}: {{typePascal}}{{/dirResult}}{{/args}};{{/method}}
|
|
type
|
|
{{#orm}}
|
|
{{^isInMormotPas}}
|
|
/// map "{{tableName}}" table
|
|
{{className}} = class(TSQLRecord)
|
|
protected
|
|
{{#fields}}
|
|
f{{name}}: {{typePascal}};
|
|
{{/fields}}
|
|
{{#hasRecords}}
|
|
public
|
|
{{#fields}}
|
|
{{#isrecord}}
|
|
property {{name}}: {{typePascal}} read f{{name}} write f{{name}}{{#unique}} stored AS_UNIQUE{{/unique}};
|
|
{{/isrecord}}
|
|
{{/fields}}
|
|
{{/hasRecords}}
|
|
published
|
|
{{#fields}}
|
|
{{^isrecord}}
|
|
{{#isSQLRecord}} // defined as {{name}}: {{typeDelphi}} on the server
|
|
{{/isSQLRecord}}
|
|
property {{name}}: {{typePascal}}{{#width}} index {{width}}{{/width}} read f{{name}} write f{{name}}{{#unique}} stored AS_UNIQUE{{/unique}};
|
|
{{/isrecord}}
|
|
{{/fields}}
|
|
end;
|
|
|
|
{{/isInMormotPas}}
|
|
{{/orm}}
|
|
{{#soa.services}}
|
|
/// service implemented by TService{{interfaceURI}}
|
|
// - you can access this service as such:
|
|
// !var a{{interfaceURI}}: I{{interfaceURI}};
|
|
// !begin
|
|
// ! a{{interfaceURI}} := TService{{interfaceURI}}.Create(aClient);
|
|
// ! // now you can use a{{interfaceURI}} methods
|
|
// !...
|
|
I{{interfaceURI}} = interface(IServiceAbstract)
|
|
['{{GUID}}']
|
|
{{#methods}}
|
|
{{verb}} {{>method}}
|
|
{{/methods}}
|
|
end;
|
|
|
|
/// implements I{{interfaceURI}} {{#uri}}from {{protocol}}://{{host}}/{{root}}/{{uri}}{{/uri}}
|
|
// - this service will run in sic{{instanceCreationName}} mode
|
|
TService{{interfaceURI}} = class(TServiceClientAbstract{{#isClientDriven}}ClientDriven{{/isClientDriven}},I{{interfaceURI}})
|
|
public
|
|
constructor Create(aClient: TSQLRestClientURI); override;
|
|
{{#methods}}
|
|
{{verb}} {{>method}}
|
|
{{/methods}}
|
|
end;
|
|
|
|
{{/soa.services}}
|
|
const
|
|
/// the server port{{#uri}}, corresponding to {{protocol}}://{{host}}{{/uri}}
|
|
SERVER_PORT = {{port}};
|
|
/// the server model root name{{#uri}}, corresponding to {{protocol}}://{{host}}{{/uri}}
|
|
SERVER_ROOT = '{{root}}';
|
|
|
|
|
|
/// return the database Model corresponding to this server
|
|
function GetModel(const aRoot: string=SERVER_ROOT): TSQLModel;
|
|
|
|
/// create a TSQLRestClientHTTP instance and connect to the server
|
|
// - it will use by default port {{port}} over root '{{root}}'{{#host}}, corresponding
|
|
// to {{protocol}}://{{host}}/{{root}}{{/host}}
|
|
{{#authClass}}
|
|
// - secure connection will be established via {{.}}
|
|
// with the supplied credentials - on connection or authentication error,
|
|
// this function will raise a corresponding exception
|
|
{{/authClass}}
|
|
function GetClient(const aServerAddress{{#authClass}}, aUserName,aPassword{{/authClass}}: string;
|
|
aServerPort: integer=SERVER_PORT; const aServerRoot: string=SERVER_ROOT;
|
|
aHttps: boolean={{#https}}true{{/https}}{{^https}}false{{/https}}): TSQLRestClientHTTP;
|
|
|
|
{{#withHelpers}}
|
|
// publish some low-level helpers for variant conversion
|
|
// - used internally: you should not need those functions in your end-user code
|
|
{{#enumerates}}
|
|
function Variant2{{name}}(const _variant: variant): {{name}};
|
|
{{/enumerates}}
|
|
{{#records}}
|
|
function Variant2{{name}}(_variant: variant): {{name}};
|
|
function {{name}}2Variant(const _record: {{name}}): variant;
|
|
{{/records}}
|
|
{{#arrays}}
|
|
function Variant2{{name}}(const _variant: variant): {{name}};
|
|
function {{name}}2Variant(const _array: {{name}}): variant;
|
|
{{/arrays}}
|
|
|
|
{{/withHelpers}}
|
|
|
|
implementation
|
|
|
|
{$HINTS OFF} // for H2164 hints of unused variables
|
|
|
|
{{#withEnumerates}}
|
|
|
|
{ Some helpers for enumerates types }
|
|
|
|
{{#enumerates}}
|
|
function Variant2{{name}}(const _variant: variant): {{name}};
|
|
begin
|
|
result := {{name}}(VariantToEnum(_variant,[{{#values}}'{{.}}'{{^-last}},{{/-last}}{{/values}}]));
|
|
end;
|
|
|
|
{{/enumerates}}
|
|
{{/withEnumerates}}
|
|
{{#withRecords}}
|
|
{{<setrec}}{{#fields}}
|
|
{{#isSimple}} result.{{fullPropName}} := _variant.{{fullPropName}};
|
|
{{/isSimple}}{{#nestedRecord}}{{>setrec}}{{/nestedRecord}}{{#fromVariant}} result.{{fullPropName}} := {{fromVariant}}(_variant.{{fullPropName}});
|
|
{{/fromVariant}}{{#nestedSimpleArray}} _arr := JSONVariantDataSafe(_variant.{{fullPropName}},jvArray);
|
|
SetLength(result.{{fullPropName}},_arr^.Count);
|
|
for _a := 0 to high(result.{{fullPropName}}) do
|
|
result.{{fullPropName}}[_a] := {{#fromVariant}}{{fromVariant}}({{/fromVariant}}_arr^.Values[_a]{{#fromVariant}}){{/fromVariant}};
|
|
{{/nestedSimpleArray}}{{#nestedRecordArray}} _arr := JSONVariantDataSafe(_variant.{{fullPropName}},jvArray);
|
|
SetLength(result.{{fullPropName}},_arr^.Count);
|
|
for _a := 0 to high(result.{{fullPropName}}) do
|
|
with result.{{fullPropName}}[_a] do begin
|
|
{{#fields}}
|
|
{{propName}} := {{#fromVariant}}{{fromVariant}}({{/fromVariant}}_arr^.Values[_a].{{propName}}{{#fromVariant}}){{/fromVariant}};
|
|
{{/fields}}
|
|
end;
|
|
{{/nestedRecordArray}}{{/fields}}{{/setrec}}
|
|
{{<getrec}}{{#fields}}
|
|
{{#isSimple}} res.SetPath('{{fullPropName}}',_record.{{fullPropName}});
|
|
{{/isSimple}}{{#nestedRecord}}{{>getrec}}{{/nestedRecord}}{{#toVariant}} res.SetPath('{{fullPropName}}',{{toVariant}}(_record.{{fullPropName}}));
|
|
{{/toVariant}}{{#nestedSimpleArray}} with res.EnsureData('{{fullPropName}}')^ do
|
|
for i := 0 to high(_record.{{fullPropName}}) do
|
|
AddValue({{#toVariant}}{{toVariant}}({{/toVariant}}_record.{{fullPropName}}[i]{{#toVariant}}){{/toVariant}});
|
|
{{/nestedSimpleArray}}{{#nestedRecordArray}} with res.EnsureData('{{fullPropName}}')^ do
|
|
for i := 0 to high(_record.{{fullPropName}}) do
|
|
with AddItem^, _record.{{fullPropName}}[i] do begin
|
|
{{#fields}}
|
|
AddNameValue('{{propName}}',{{#toVariant}}{{toVariant}}({{/toVariant}}{{propName}}{{#toVariant}}){{/toVariant}});
|
|
{{/fields}}
|
|
end;
|
|
{{/nestedRecordArray}}{{/fields}}{{/getrec}}{ Some helpers for record types }
|
|
{{#records}}
|
|
|
|
function Variant2{{name}}(_variant: variant): {{name}};
|
|
var _a: integer;
|
|
_arr: PJSONVariantData;
|
|
begin
|
|
{{>setrec}}
|
|
end;
|
|
|
|
function {{name}}2Variant(const _record: {{name}}): variant;
|
|
var i: integer;
|
|
res: TJSONVariantData;
|
|
begin
|
|
res.Init;
|
|
{{>getrec}}
|
|
result := variant(res);
|
|
end;
|
|
{{/records}}
|
|
|
|
{{/withRecords}}
|
|
{{#withArrays}}
|
|
|
|
{ Some helpers for dynamic array types }
|
|
|
|
{{#arrays}}
|
|
function Variant2{{name}}(const _variant: variant): {{name}};
|
|
var i: integer;
|
|
arr: PJSONVariantData;
|
|
begin
|
|
arr := JSONVariantDataSafe(_variant,jvArray);
|
|
SetLength(result,arr^.Count);
|
|
for i := 0 to arr^.Count-1 do
|
|
result[i] := {{#fromVariant}}{{fromVariant}}{{/fromVariant}}(arr^.Values[i]);
|
|
end;
|
|
|
|
function {{name}}2Variant(const _array: {{name}}): variant;
|
|
var i: integer;
|
|
res: TJSONVariantData;
|
|
begin
|
|
res.Init;
|
|
for i := 0 to high(_array) do
|
|
res.AddValue({{#toVariant}}{{toVariant}}{{/toVariant}}(_array[i]));
|
|
result := variant(res);
|
|
end;
|
|
|
|
{{/arrays}}
|
|
{{/withArrays}}
|
|
|
|
{$HINTS ON} // for H2164 hints of unused variables
|
|
|
|
function GetModel(const aRoot: string): TSQLModel;
|
|
begin
|
|
result := TSQLModel.Create([{{#orm}}{{className}}{{comma}}{{/orm}}],aRoot);
|
|
end;
|
|
|
|
function GetClient(const aServerAddress{{#authClass}}, aUserName,aPassword{{/authClass}}: string;
|
|
aServerPort: integer; const aServerRoot: string; aHttps: boolean): TSQLRestClientHTTP;
|
|
begin
|
|
result := TSQLRestClientHTTP.Create(aServerAddress,aServerPort,
|
|
GetModel(aServerRoot),true,aHttps); // aOwnModel=true
|
|
try
|
|
if (not result.Connect) or (result.ServerTimeStamp=0) then
|
|
raise ERestException.CreateFmt('Impossible to connect to %s:%d server',
|
|
[aServerAddress,aServerPort]);
|
|
{{#authClass}}
|
|
if not result.SetUser({{.}},aUserName,aPassword) then
|
|
raise ERestException.CreateFmt('%s:%d server rejected "%s" credentials',
|
|
[aServerAddress,aServerPort,aUserName]);
|
|
{{/authClass}}
|
|
except
|
|
result.Free;
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
{{#soa.services}}
|
|
|
|
{ TService{{interfaceURI}} }
|
|
|
|
constructor TService{{interfaceURI}}.Create(aClient: TSQLRestClientURI);
|
|
begin
|
|
fServiceName := '{{interfaceURI}}';
|
|
fServiceURI := '{{uri}}';
|
|
fInstanceImplementation := sic{{instanceCreationName}};
|
|
fContractExpected := '{{contractExpected}}';
|
|
inherited Create(aClient);
|
|
end;
|
|
|
|
{{#methods}}
|
|
{{verb}} TService{{interfaceURI}}.{{>method}}
|
|
var res: TVariantDynArray;
|
|
begin
|
|
fClient.CallRemoteService(self,'{{methodName}}',{{ArgsOutputCount}}, // raise EServiceException on error
|
|
[{{#args}}{{#dirInput}}{{#toVariant}}{{toVariant}}({{argName}}){{/toVariant}}{{^toVariant}}{{argName}}{{/toVariant}}{{commaInSingle}}{{/dirInput}}{{/args}}],res{{#resultIsServiceCustomAnswer}},true{{/resultIsServiceCustomAnswer}});
|
|
{{#args}}{{#dirOutput}}{{#isObject}} {{argName}}.Free; // avoid memory leak
|
|
{{/isObject}} {{argName}} := {{#fromVariant}}{{fromVariant}}({{/fromVariant}}res[{{indexOutResult}}{{#fromVariant}}){{/fromVariant}};
|
|
{{/dirOutput}}{{/args}}end;
|
|
|
|
{{/methods}}
|
|
{{/soa.services}}
|
|
|
|
end. |