Files
lazarus-ccr/wst/trunk/base_soap_formatter.pas
inoussa 1069954eba Record support :
- Field may be hidden by calling SetFieldSerializationVisibility()
  - Field may be mapped to XML Attribute by calling RegisterAttributeProperty()

Some methods and routines have been marked "inline". By default the "inline" modifier is not enable. To enable it
uncomment the "//{$DEFINE USE_INLINE}" line in wst_global.inc.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@244 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2007-08-19 21:04:16 +00:00

1816 lines
49 KiB
ObjectPascal

{
This file is part of the Web Service Toolkit
Copyright (c) 2006 by Inoussa OUEDRAOGO
This file is provide under modified LGPL licence
( the files COPYING.modifiedLGPL and COPYING.LGPL).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
}
{$INCLUDE wst_global.inc}
unit base_soap_formatter;
interface
uses
Classes, SysUtils, TypInfo, Contnrs,
{$IFNDEF FPC}xmldom, wst_delphi_xml{$ELSE}DOM{$ENDIF},
base_service_intf;
const
sPROTOCOL_NAME = 'SOAP';
sXML_NS = 'xmlns';
sXSI_NS = 'http://www.w3.org/1999/XMLSchema-instance';
sTYPE = 'type';
sNIL = 'nil';
sSOAP_ENC = 'http://schemas.xmlsoap.org/soap/encoding/';
sSOAP_ENC_ABR = 'SOAP-ENC';
sARRAY_TYPE = 'arrayType';
sCONTENT_TYPE = 'contenttype';
sFORMAT = 'format';
sSOAP_CONTENT_TYPE = 'text/xml';
sHEADER = 'Header';
sENVELOPE = 'Envelope';
type
TwstXMLDocument = {$IFNDEF FPC}wst_delphi_xml.TXMLDocument{$ELSE}TXMLDocument{$ENDIF};
TEnumIntType = Int64;
{ ESOAPException }
ESOAPException = class(EBaseRemoteException)
End;
{ TStackItem }
TStackItem = class
private
FEmbeddedScopeCount: Integer;
FNameSpace: string;
FScopeObject: TDOMNode;
FScopeType: TScopeType;
protected
function GetItemsCount() : Integer;virtual;
Public
constructor Create(AScopeObject : TDOMNode;AScopeType : TScopeType);
function FindNode(var ANodeName : string):TDOMNode;virtual;abstract;
procedure SetNameSpace(const ANameSpace : string);
property ScopeObject : TDOMNode Read FScopeObject;
property ScopeType : TScopeType Read FScopeType;
property NameSpace : string Read FNameSpace;
property ItemsCount : Integer read GetItemsCount;
property EmbeddedScopeCount : Integer read FEmbeddedScopeCount;
function BeginEmbeddedScope() : Integer;
function EndEmbeddedScope() : Integer;
End;
{ TObjectStackItem }
TObjectStackItem = class(TStackItem)
Public
function FindNode(var ANodeName : string):TDOMNode;override;
End;
{ TAbstractArrayStackItem }
TAbstractArrayStackItem = class(TStackItem)
private
FItemList : TDOMNodeList;
FIndex : Integer;
FItemName : string;
protected
procedure EnsureListCreated();
function GetItemsCount() : Integer;override;
function CreateList(const ANodeName : string):TDOMNodeList;virtual;abstract;
public
constructor Create(
AScopeObject : TDOMNode;
const AScopeType : TScopeType;
const AItemName : string
);
destructor Destroy();override;
function FindNode(var ANodeName : string):TDOMNode;override;
end;
{ TScopedArrayStackItem }
TScopedArrayStackItem = class(TAbstractArrayStackItem)
protected
function CreateList(const ANodeName : string):TDOMNodeList;override;
end;
{ TEmbeddedArrayStackItem }
TEmbeddedArrayStackItem = class(TAbstractArrayStackItem)
protected
function CreateList(const ANodeName : string):TDOMNodeList;override;
end;
TSOAPEncodingStyle = ( Literal, Encoded );
TSOAPDocumentStyle = ( RPC, Document );
{$M+}
{ TSOAPBaseFormatter }
TSOAPBaseFormatter = class(TSimpleFactoryItem,IFormatterBase)
private
FContentType: string;
FEncodingStyle: TSOAPEncodingStyle;
FStyle: TSOAPDocumentStyle;
FHeaderEnterCount : Integer;
FNameSpaceCounter : Integer;
FDoc : TwstXMLDocument;
FStack : TObjectStack;
FKeepedStyle : TSOAPDocumentStyle;
FKeepedEncoding : TSOAPEncodingStyle;
FSerializationStyle : TSerializationStyle;
procedure InternalClear(const ACreateDoc : Boolean);{$IFDEF USE_INLINE}inline;{$ENDIF}
function NextNameSpaceCounter():Integer;{$IFDEF USE_INLINE}inline;{$ENDIF}
function HasScope():Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
procedure CheckScope();{$IFDEF USE_INLINE}inline;{$ENDIF}
function InternalPutData(
Const AName : String;
Const ATypeInfo : PTypeInfo;
Const AData : string
):TDOMNode;
function PutEnum(
Const AName : String;
Const ATypeInfo : PTypeInfo;
Const AData : TEnumIntType
):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
function PutBool(
Const AName : String;
Const ATypeInfo : PTypeInfo;
Const AData : Boolean
):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
function PutInt64(
Const AName : String;
Const ATypeInfo : PTypeInfo;
Const AData : Int64
):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
function PutStr(
Const AName : String;
Const ATypeInfo : PTypeInfo;
Const AData : String
):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
function PutFloat(
Const AName : String;
Const ATypeInfo : PTypeInfo;
Const AData : Extended
):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
procedure PutObj(
Const AName : String;
Const ATypeInfo : PTypeInfo;
Const AData : TObject
);{$IFDEF USE_INLINE}inline;{$ENDIF}
procedure PutRecord(
const AName : string;
const ATypeInfo : PTypeInfo;
const AData : Pointer
);{$IFDEF USE_INLINE}inline;{$ENDIF}
function GetNodeValue(var AName : String):DOMString;
procedure GetEnum(
Const ATypeInfo : PTypeInfo;
Var AName : String;
Var AData : TEnumIntType
);{$IFDEF USE_INLINE}inline;{$ENDIF}
procedure GetBool(
Const ATypeInfo : PTypeInfo;
Var AName : String;
Var AData : Boolean
);{$IFDEF USE_INLINE}inline;{$ENDIF}
{$IFDEF FPC}
procedure GetInt(
Const ATypeInfo : PTypeInfo;
Var AName : String;
Var AData : Integer
);{$IFDEF USE_INLINE}inline;{$ENDIF}
{$ENDIF}
procedure GetInt64(
Const ATypeInfo : PTypeInfo;
Var AName : String;
Var AData : Int64
);{$IFDEF USE_INLINE}inline;{$ENDIF}
procedure GetFloat(
Const ATypeInfo : PTypeInfo;
Var AName : String;
Var AData : Extended
);{$IFDEF USE_INLINE}inline;{$ENDIF}
procedure GetStr(
Const ATypeInfo : PTypeInfo;
Var AName : String;
Var AData : String
);{$IFDEF USE_INLINE}inline;{$ENDIF}
procedure GetObj(
Const ATypeInfo : PTypeInfo;
Var AName : String;
Var AData : TObject
);{$IFDEF USE_INLINE}inline;{$ENDIF}
procedure GetRecord(
const ATypeInfo : PTypeInfo;
var AName : String;
var AData : Pointer
);{$IFDEF USE_INLINE}inline;{$ENDIF}
protected
function GetXmlDoc():TwstXMLDocument;{$IFDEF USE_INLINE}inline;{$ENDIF}
function PushStack(AScopeObject : TDOMNode):TStackItem;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
function PushStack(
AScopeObject : TDOMNode;
const AStyle : TArrayStyle;
const AItemName : string
):TStackItem;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
function FindAttributeByValueInNode(
Const AAttValue : String;
Const ANode : TDOMNode;
Out AResAtt : string
):boolean;
function FindAttributeByNameInNode(
Const AAttName : String;
Const ANode : TDOMNode;
Out AResAttValue : string
):boolean;
function FindAttributeByValueInScope(Const AAttValue : String):String;
function FindAttributeByNameInScope(Const AAttName : String):String;
function GetNameSpaceShortName(
const ANameSpace : string;
const ACreateIfNotFound : Boolean
):shortstring;{$IFDEF USE_INLINE}inline;{$ENDIF}
protected
function GetCurrentScope():String;
function GetCurrentScopeObject():TDOMElement;
function StackTop():TStackItem;{$IFDEF USE_INLINE}inline;{$ENDIF}
function PopStack():TStackItem;{$IFDEF USE_INLINE}inline;{$ENDIF}
procedure ClearStack();{$IFDEF USE_INLINE}inline;{$ENDIF}
procedure BeginScope(
Const AScopeName,ANameSpace : string;
Const ANameSpaceShortName : string ;
Const AScopeType : TScopeType;
const AStyle : TArrayStyle
);
function InternalBeginScopeRead(
var AScopeName : string;
const ATypeInfo : PTypeInfo;
const AScopeType : TScopeType;
const AStyle : TArrayStyle;
const AItemName : string
):Integer;
procedure SetSerializationStyle(const ASerializationStyle : TSerializationStyle);
function GetSerializationStyle():TSerializationStyle;
procedure SetStyleAndEncoding(
const AStyle : TSOAPDocumentStyle;
const AEncoding : TSOAPEncodingStyle
);
procedure RestoreStyleAndEncoding();
procedure Prepare();
function ReadHeaders(ACallContext : ICallContext):Integer;
function WriteHeaders(ACallContext : ICallContext):Integer;
public
constructor Create();override;
destructor Destroy();override;
procedure Clear();
procedure BeginObject(
Const AName : string;
Const ATypeInfo : PTypeInfo
);
procedure BeginArray(
const AName : string;
const ATypeInfo : PTypeInfo;
const AItemTypeInfo : PTypeInfo;
const ABounds : Array Of Integer;
const AStyle : TArrayStyle
);
procedure NilCurrentScope();
function IsCurrentScopeNil():Boolean;
procedure EndScope();
procedure AddScopeAttribute(Const AName,AValue : string);
function BeginObjectRead(
var AScopeName : string;
const ATypeInfo : PTypeInfo
) : Integer;
function BeginArrayRead(
var AScopeName : string;
const ATypeInfo : PTypeInfo;
const AStyle : TArrayStyle;
const AItemName : string
):Integer;
procedure EndScopeRead();
procedure BeginHeader();
procedure EndHeader();
procedure Put(
const AName : string;
const ATypeInfo : PTypeInfo;
const AData
);
procedure PutScopeInnerValue(
const ATypeInfo : PTypeInfo;
const AData
);
procedure Get(
const ATypeInfo : PTypeInfo;
var AName : string;
var AData
);
procedure GetScopeInnerValue(
const ATypeInfo : PTypeInfo;
var AData
);
function ReadBuffer(const AName : string) : string;
procedure SaveToStream(AStream : TStream);
procedure LoadFromStream(AStream : TStream);
procedure Error(Const AMsg:string);overload;
procedure Error(Const AMsg:string; Const AArgs : array of const);overload;
Published
property EncodingStyle : TSOAPEncodingStyle Read FEncodingStyle Write FEncodingStyle;
property ContentType : string Read FContentType Write FContentType;
property Style : TSOAPDocumentStyle Read FStyle Write FStyle;
End;
{$M-}
implementation
Uses {$IFNDEF FPC}XMLDoc,XMLIntf,{$ELSE}XMLWrite, XMLRead,wst_fpc_xml,{$ENDIF}
StrUtils, imp_utils;
{ TStackItem }
function TStackItem.GetItemsCount: Integer;
begin
Result := GetNodeItemsCount(ScopeObject);
end;
constructor TStackItem.Create(AScopeObject: TDOMNode; AScopeType: TScopeType);
begin
FScopeObject := AScopeObject;
FScopeType := AScopeType;
end;
procedure TStackItem.SetNameSpace(const ANameSpace: string);
begin
FNameSpace := ANameSpace;
end;
function TStackItem.BeginEmbeddedScope(): Integer;
begin
Inc(FEmbeddedScopeCount);
Result := FEmbeddedScopeCount;
end;
function TStackItem.EndEmbeddedScope(): Integer;
begin
if ( FEmbeddedScopeCount < 1 ) then begin
raise Exception.Create('Invalid op�ration on scope, their are no embedded scope.');
end;
Dec(FEmbeddedScopeCount);
Result := FEmbeddedScopeCount;
end;
{ TObjectStackItem }
function TObjectStackItem.FindNode(var ANodeName: string): TDOMNode;
begin
{$IFNDEF FPC}
Result := wst_delphi_xml.FindNode(ScopeObject,ANodeName);
{$ELSE}
Result := ScopeObject.FindNode(ANodeName);
{$ENDIF}
end;
{ TAbstractArrayStackItem }
procedure TAbstractArrayStackItem.EnsureListCreated();
begin
if ( FItemList = nil ) then begin
FItemList := CreateList(FItemName);
end;
end;
function TAbstractArrayStackItem.GetItemsCount(): Integer;
begin
EnsureListCreated();
if Assigned(FItemList) then begin
Result := GetNodeListCount(FItemList);
end else begin
Result := 0;
end;
end;
constructor TAbstractArrayStackItem.Create(
AScopeObject : TDOMNode;
const AScopeType : TScopeType;
const AItemName : string
);
begin
inherited Create(AScopeObject,AScopeType);
FItemName := AItemName;
end;
destructor TAbstractArrayStackItem.Destroy();
begin
if Assigned(FItemList) then
ReleaseDomNode(FItemList);
inherited Destroy();
end;
function TAbstractArrayStackItem.FindNode(var ANodeName: string): TDOMNode;
begin
EnsureListCreated();
if ( FIndex >= GetNodeListCount(FItemList) ) then
raise ESOAPException.CreateFmt('Index out of bound : %d; Node Name = "%s"; Parent Node = "%s"',[FIndex,ANodeName,ScopeObject.NodeName]);
Result:= FItemList.Item[FIndex];
Inc(FIndex);
ANodeName := Result.NodeName;
end;
{ TSOAPBaseFormatter }
procedure TSOAPBaseFormatter.ClearStack();
Var
i, c : Integer;
begin
c := FStack.Count;
For I := 1 To c Do
FStack.Pop().Free();
end;
function TSOAPBaseFormatter.PushStack(AScopeObject : TDOMNode) : TStackItem;
begin
Result := FStack.Push(TObjectStackItem.Create(AScopeObject,stObject)) as TStackItem;
end;
function TSOAPBaseFormatter.PushStack(
AScopeObject : TDOMNode;
const AStyle : TArrayStyle;
const AItemName : string
): TStackItem;
begin
case AStyle of
asScoped : Result := FStack.Push(TScopedArrayStackItem.Create(AScopeObject,stArray,AItemName)) as TStackItem;
asEmbeded : Result := FStack.Push(TEmbeddedArrayStackItem.Create(AScopeObject,stArray,AItemName)) as TStackItem;
else
Assert(False);
end;
end;
function TSOAPBaseFormatter.BeginObjectRead(
var AScopeName : string;
const ATypeInfo : PTypeInfo
): Integer;
begin
Result := InternalBeginScopeRead(AScopeName,ATypeInfo,stObject,asNone,'');
end;
function TSOAPBaseFormatter.BeginArrayRead(
var AScopeName : string;
const ATypeInfo : PTypeInfo;
const AStyle : TArrayStyle;
const AItemName : string
): Integer;
begin
Result := InternalBeginScopeRead(AScopeName,ATypeInfo,stArray,AStyle,AItemName);
end;
procedure TSOAPBaseFormatter.EndScopeRead();
begin
PopStack().Free();
end;
procedure TSOAPBaseFormatter.BeginHeader();
begin
if ( FHeaderEnterCount <= 0 ) then begin
Inc(FHeaderEnterCount);
Prepare();
BeginScope(sHEADER,sSOAP_ENV,sSOAP_ENV_ABR,stObject,asNone);
SetStyleAndEncoding(Document,Literal);
end;
end;
procedure TSOAPBaseFormatter.EndHeader();
begin
if ( FHeaderEnterCount > 0 ) then begin
Dec(FHeaderEnterCount);
RestoreStyleAndEncoding();
EndScope();
end;
end;
procedure TSOAPBaseFormatter.InternalClear(const ACreateDoc: Boolean);
begin
ClearStack();
ReleaseDomNode(FDoc);
FDoc := nil;
if ACreateDoc then
FDoc := CreateDoc();
end;
function TSOAPBaseFormatter.NextNameSpaceCounter(): Integer;
begin
Inc(FNameSpaceCounter);
Result := FNameSpaceCounter;
end;
function TSOAPBaseFormatter.HasScope(): Boolean;
begin
Result := FStack.AtLeast(1);
end;
function TSOAPBaseFormatter.FindAttributeByValueInNode(
Const AAttValue : String;
Const ANode : TDOMNode;
Out AResAtt : string
):boolean;
Var
i,c : Integer;
begin
AResAtt := '';
if Assigned(ANode) and
Assigned(ANode.Attributes) and
( ANode.Attributes.Length > 0 )
then begin
c := Pred(ANode.Attributes.Length);
For i := 0 To c Do Begin
If AnsiSameText(AAttValue,ANode.Attributes.Item[i].NodeValue) Then Begin
AResAtt := ANode.Attributes.Item[i].NodeName;
Result := True;
Exit;
End;
End;
end;
Result := False;
end;
function TSOAPBaseFormatter.FindAttributeByNameInNode(
const AAttName: String;
const ANode: TDOMNode;
Out AResAttValue: string
): boolean;
var
i,c : Integer;
begin
AResAttValue := '';
If Assigned(ANode) And Assigned(ANode.Attributes) Then Begin
c := Pred(ANode.Attributes.Length);
For i := 0 To c Do Begin
If AnsiSameText(AAttName,ANode.Attributes.Item[i].NodeName) Then Begin
AResAttValue := ANode.Attributes.Item[i].NodeValue;
Result := True;
Exit;
End;
End;
End;
Result := False;
end;
function TSOAPBaseFormatter.FindAttributeByValueInScope(const AAttValue: String): String;
Var
tmpNode : TDOMNode;
begin
If HasScope() Then Begin
tmpNode := GetCurrentScopeObject();
While Assigned(tmpNode) Do Begin
If FindAttributeByValueInNode(AAttValue,tmpNode,Result) Then
Exit;
tmpNode := tmpNode.ParentNode;
End;
End;
Result := '';
end;
function TSOAPBaseFormatter.FindAttributeByNameInScope(const AAttName: String): String;
var
tmpNode : TDOMNode;
begin
if HasScope() then begin
tmpNode := GetCurrentScopeObject();
while Assigned(tmpNode) do begin
if FindAttributeByNameInNode(AAttName,tmpNode,Result) then
Exit;
tmpNode := tmpNode.ParentNode;
end;
end;
Result := '';
end;
function TSOAPBaseFormatter.GetNameSpaceShortName(
const ANameSpace : string;
const ACreateIfNotFound : Boolean
): shortstring;
begin
Result := FindAttributeByValueInScope(ANameSpace);
if IsStrEmpty(Result) then begin
if ACreateIfNotFound then begin
Result := 'ns' + IntToStr(NextNameSpaceCounter());
AddScopeAttribute('xmlns:'+Result, ANameSpace);
end;
end else begin
Result := Copy(Result,Length('xmlns:')+1,MaxInt);
end;
end;
procedure TSOAPBaseFormatter.CheckScope();
begin
If Not HasScope() Then
Error('There is no scope.');
end;
function ExtractNameSpaceShortName(const ANameSpaceDeclaration : string):string;
var
i : integer;
begin
i := AnsiPos(sXML_NS,ANameSpaceDeclaration);
if ( i > 0 ) then begin
Result := Copy(ANameSpaceDeclaration, (i + Length(sXML_NS) + 1 ), MaxInt );
end else begin
Result := '';
end;
end;
function TSOAPBaseFormatter.InternalPutData(
const AName : String;
const ATypeInfo : PTypeInfo;
const AData : string
): TDOMNode;
Var
namespaceLongName, namespaceShortName, strName, strNodeName, s : string;
regItem : TTypeRegistryItem;
begin
strNodeName := AName;
if ( Style = Document ) then begin
namespaceShortName := Copy(FindAttributeByValueInScope(StackTop().NameSpace),AnsiPos(':',namespaceShortName) + 1,MaxInt);
if not IsStrEmpty(namespaceShortName) then begin
s := ExtractNameSpaceShortName(namespaceShortName);
if not IsStrEmpty(s) then
strNodeName := s + ':' + strNodeName;
end;
end;
if ( FSerializationStyle = ssNodeSerialization ) then begin
Result := FDoc.CreateElement(strNodeName);
Result.AppendChild(FDoc.CreateTextNode(AData));
GetCurrentScopeObject().AppendChild(Result);
If ( EncodingStyle = Encoded ) Then Begin
regItem := GetTypeRegistry().ItemByTypeInfo[ATypeInfo];
strName := regItem.DeclaredName;
namespaceLongName := regItem.NameSpace;
If Not IsStrEmpty(namespaceLongName) Then Begin
namespaceShortName := FindAttributeByValueInScope(namespaceLongName);
If IsStrEmpty(namespaceShortName) Then Begin
namespaceShortName := Format('ns%d',[NextNameSpaceCounter()]);
AddScopeAttribute(sXML_NS + ':'+namespaceShortName,namespaceLongName);
End Else Begin
namespaceShortName := ExtractNameSpaceShortName(namespaceShortName);//Copy(namespaceShortName,AnsiPos(':',namespaceShortName) + 1,MaxInt);
End;
strName := Format('%s:%s',[namespaceShortName,strName])
End;
namespaceShortName := GetNameSpaceShortName(sXSI_NS,True);
if not IsStrEmpty(namespaceShortName) then
namespaceShortName := namespaceShortName + ':';
(Result As TDOMElement).SetAttribute(namespaceShortName + sTYPE,strName);
End;
end else begin
Result := GetCurrentScopeObject();
(Result as TDOMElement).SetAttribute(strNodeName,AData);
end;
end;
function TSOAPBaseFormatter.PutEnum(
const AName: String;
const ATypeInfo: PTypeInfo;
const AData: TEnumIntType
): TDOMNode;
begin
Result := InternalPutData(
AName,
ATypeInfo,
GetTypeRegistry().ItemByTypeInfo[ATypeInfo].GetExternalPropertyName(GetEnumName(ATypeInfo,AData))
);
end;
function TSOAPBaseFormatter.PutBool(
const AName : String;
const ATypeInfo : PTypeInfo;
const AData : Boolean
): TDOMNode;
begin
Result := InternalPutData(AName,ATypeInfo,LowerCase(BoolToStr(AData)));
end;
function TSOAPBaseFormatter.PutInt64(
const AName : String;
const ATypeInfo : PTypeInfo;
const AData : Int64
): TDOMNode;
begin
Result := InternalPutData(AName,ATypeInfo,IntToStr(AData));
end;
function TSOAPBaseFormatter.PutStr(
const AName: String;
const ATypeInfo: PTypeInfo;
const AData: String
):TDOMNode;
begin
Result := InternalPutData(AName,ATypeInfo,AData);
end;
procedure TSOAPBaseFormatter.PutObj(
const AName : String;
const ATypeInfo : PTypeInfo;
const AData : TObject
);
begin
TBaseRemotableClass(GetTypeData(ATypeInfo)^.ClassType).Save(AData As TBaseRemotable, Self,AName,ATypeInfo);
end;
procedure TSOAPBaseFormatter.PutRecord(
const AName : string;
const ATypeInfo : PTypeInfo;
const AData : Pointer
);
begin
TRemotableRecordEncoder.Save(AData,Self,AName,ATypeInfo);
end;
function TSOAPBaseFormatter.PutFloat(
const AName : String;
const ATypeInfo : PTypeInfo;
const AData : Extended
):TDOMNode;
Var
s, frmt : string;
prcsn : Integer;
{$IFDEF FPC} {$IFNDEF FPC_211} i : Integer; {$ENDIF}{$ENDIF}
begin
Case GetTypeData(ATypeInfo)^.FloatType Of
ftSingle,
ftCurr,
ftComp : prcsn := 7;
ftDouble,
ftExtended : prcsn := 15;
End;
frmt := '#.' + StringOfChar('#',prcsn) + 'E-0';
{$IFDEF FPC}
{$IFDEF FPC_211}
s := FormatFloat(frmt,AData,wst_FormatSettings);
{$ELSE}
s := FormatFloat(frmt,AData);
i := Pos(',',s);
If ( i > 0 ) Then
s[i] := '.';
{$ENDIF}
{$ELSE}
s := FormatFloat(frmt,AData,wst_FormatSettings);
{$ENDIF}
Result := InternalPutData(AName,ATypeInfo,s);
end;
function TSOAPBaseFormatter.GetNodeValue(var AName: String): DOMString;
Var
locElt : TDOMNode;
namespaceShortName, strNodeName, s : string;
begin
strNodeName := AName;
if ( Style = Document ) then begin
namespaceShortName := Copy(FindAttributeByValueInScope(StackTop().NameSpace),AnsiPos(':',namespaceShortName) + 1,MaxInt);
if not IsStrEmpty(namespaceShortName) then begin
s := ExtractNameSpaceShortName(namespaceShortName);
if not IsStrEmpty(s) then
strNodeName := s + ':' + strNodeName;
end;
end;
if ( FSerializationStyle = ssNodeSerialization ) then begin
locElt := StackTop().FindNode(strNodeName) As TDOMElement;
end else begin
locElt := GetCurrentScopeObject().GetAttributeNode(strNodeName);
end;
if Assigned(locElt) then begin
if locElt.HasChildNodes then
Result := locElt.FirstChild.NodeValue
else
Result := locElt.NodeValue;
end else begin
Error('Param or Attribute not found : "%s"',[AName]);
end;
end;
procedure TSOAPBaseFormatter.GetEnum(
const ATypeInfo: PTypeInfo;
var AName: String;
var AData: TEnumIntType
);
Var
locBuffer : String;
begin
locBuffer := Trim(GetNodeValue(AName));
If IsStrEmpty(locBuffer) Then
AData := 0
Else
AData := GetEnumValue(ATypeInfo,locBuffer)
End;
procedure TSOAPBaseFormatter.GetBool(
const ATypeInfo : PTypeInfo;
var AName : String;
var AData : Boolean
);
Var
locBuffer : String;
begin
locBuffer := LowerCase(Trim(GetNodeValue(AName)));
If IsStrEmpty(locBuffer) Then
AData := False
Else
AData := StrToBool(locBuffer);
end;
{$IFDEF FPC}
procedure TSOAPBaseFormatter.GetInt(
const ATypeInfo: PTypeInfo;
var AName: String;
var AData: Integer
);
begin
AData := StrToIntDef(Trim(GetNodeValue(AName)),0);
end;
{$ENDIF}
procedure TSOAPBaseFormatter.GetInt64(
const ATypeInfo : PTypeInfo;
var AName : String;
var AData : Int64
);
begin
AData := StrToInt64Def(Trim(GetNodeValue(AName)),0);
end;
procedure TSOAPBaseFormatter.GetFloat(
const ATypeInfo : PTypeInfo;
var AName : String;
var AData : Extended
);
begin
{$IFDEF FPC}
{$IFDEF FPC_211}
AData := StrToFloatDef(Trim(GetNodeValue(AName)),0,wst_FormatSettings);
{$ELSE}
AData := StrToFloatDef(Trim(GetNodeValue(AName)),0);
{$ENDIF}
{$ELSE}
AData := StrToFloatDef(Trim(GetNodeValue(AName)),0,wst_FormatSettings);
{$ENDIF}
//AData := StrToFloatDef(Trim(GetNodeValue(AName)),0,wst_FormatSettings);
end;
procedure TSOAPBaseFormatter.GetStr(
const ATypeInfo : PTypeInfo;
var AName : String;
var AData : String
);
begin
AData := GetNodeValue(AName);
end;
procedure TSOAPBaseFormatter.GetObj(
const ATypeInfo : PTypeInfo;
var AName : String;
var AData : TObject
);
begin
TBaseRemotableClass(GetTypeData(ATypeInfo)^.ClassType).Load(AData, Self,AName,ATypeInfo);
end;
procedure TSOAPBaseFormatter.GetRecord(
const ATypeInfo : PTypeInfo;
var AName : String;
var AData : Pointer
);
begin
TRemotableRecordEncoder.Load(AData, Self,AName,ATypeInfo);
end;
function TSOAPBaseFormatter.GetXmlDoc(): TwstXMLDocument;
begin
Result := FDoc;
end;
function TSOAPBaseFormatter.GetCurrentScope(): String;
begin
CheckScope();
Result:= GetCurrentScopeObject().NodeName;
end;
function TSOAPBaseFormatter.GetCurrentScopeObject(): TDOMElement;
begin
Result := StackTop().ScopeObject As TDOMElement;
end;
function TSOAPBaseFormatter.StackTop(): TStackItem;
begin
CheckScope();
Result := FStack.Peek() as TStackItem;
end;
function TSOAPBaseFormatter.PopStack(): TStackItem;
begin
CheckScope();
Result := FStack.Pop() as TStackItem;
end;
constructor TSOAPBaseFormatter.Create();
begin
Inherited Create();
FContentType := sSOAP_CONTENT_TYPE;
FStack := TObjectStack.Create();
FDoc := CreateDoc();
end;
destructor TSOAPBaseFormatter.Destroy();
begin
ReleaseDomNode(FDoc);
ClearStack();
FStack.Free();
inherited Destroy();
end;
procedure TSOAPBaseFormatter.Clear();
begin
InternalClear(True);
end;
procedure TSOAPBaseFormatter.BeginObject(
const AName : string;
const ATypeInfo : PTypeInfo
);
Var
typData : TTypeRegistryItem;
nmspc,nmspcSH, xsiNmspcSH : string;
mustAddAtt : Boolean;
strNodeName : string;
begin
typData := GetTypeRegistry().Find(ATypeInfo,False);
If Not Assigned(typData) Then
Error('Object type not registered : %s',[IfThen(Assigned(ATypeInfo),ATypeInfo^.Name,'')]);
mustAddAtt := False;
nmspc := typData.NameSpace;
If IsStrEmpty(nmspc) Then
nmspcSH := 'tns'
Else Begin
nmspcSH := FindAttributeByValueInScope(nmspc);
If IsStrEmpty(nmspcSH) Then Begin
nmspcSH := 'ns' + IntToStr(NextNameSpaceCounter());
If HasScope() Then
AddScopeAttribute('xmlns:'+nmspcSH, nmspc)
Else Begin
mustAddAtt := True;
End;
End Else Begin
nmspcSH := Copy(nmspcSH,Length('xmlns:')+1,MaxInt);
End;
End;
if ( Style = Document ) then begin
strNodeName := nmspcSH + ':' + AName;
end else begin
strNodeName := AName;
end;
BeginScope(strNodeName,'','',stObject,asNone);
If mustAddAtt Then
AddScopeAttribute('xmlns:'+nmspcSH, nmspc);
if ( EncodingStyle = Encoded ) then begin
xsiNmspcSH := GetNameSpaceShortName(sXSI_NS,True);
if not IsStrEmpty(xsiNmspcSH) then
xsiNmspcSH := xsiNmspcSH + ':';
AddScopeAttribute(xsiNmspcSH + sTYPE,Format('%s:%s',[nmspcSH,typData.DeclaredName]));
end;
StackTop().SetNameSpace(nmspc);
end;
procedure TSOAPBaseFormatter.BeginArray(
const AName : string;
const ATypeInfo : PTypeInfo;
const AItemTypeInfo : PTypeInfo;
const ABounds : Array Of Integer;
const AStyle : TArrayStyle
);
Var
typData : TTypeRegistryItem;
nmspc,nmspcSH : string;
i,j, k : Integer;
strNodeName : string;
xsiNmspcSH : string;
begin
if ( Length(ABounds) < 2 ) then begin
Error('Invalid array bounds.');
end;
i := ABounds[0];
j := ABounds[1];
k := j - i + 1;
if ( k < 0 ) then begin
Error('Invalid array bounds.');
end;
typData := GetTypeRegistry().Find(ATypeInfo,False);
if not Assigned(typData) then begin
Error('Array type not registered.');
end;
nmspc := typData.NameSpace;
if IsStrEmpty(nmspc) then begin
nmspcSH := 'tns'
end else begin
nmspcSH := FindAttributeByValueInScope(nmspc);
if IsStrEmpty(nmspcSH) then begin
nmspcSH := 'ns' + IntToStr(NextNameSpaceCounter());
AddScopeAttribute('xmlns:'+nmspcSH, nmspc);
end else begin
nmspcSH := Copy(nmspcSH,Length('xmlns:')+1,MaxInt);
end;
end;
if ( Style = Document ) then begin
strNodeName := nmspcSH + ':' + AName;
end else begin
strNodeName := AName;
end;
//if ( AStyle = asScoped ) then begin
BeginScope(strNodeName,'','',stArray,AStyle);
//end;
if ( EncodingStyle = Encoded ) then begin
//AddScopeAttribute(sXSI_TYPE,nmspc);
//SOAP-ENC:arrayType="xsd:int[2]"
{AddScopeAttribute(
Format('%s:%s',[sSOAP_ENC_ABR,sARRAY_TYPE]) ,
Format('%s:%s[%d]',[nmspcSH,typData.DeclaredName,k])
);}
xsiNmspcSH := GetNameSpaceShortName(sXSI_NS,True);
if not IsStrEmpty(xsiNmspcSH) then
xsiNmspcSH := xsiNmspcSH + ':';
AddScopeAttribute(xsiNmspcSH + sTYPE,Format('%s:%s',[nmspcSH,typData.DeclaredName]));
end;
StackTop().SetNameSpace(nmspc);
end;
procedure TSOAPBaseFormatter.NilCurrentScope();
var
nmspcSH : shortstring;
begin
CheckScope();
nmspcSH := FindAttributeByValueInScope(sXSI_NS);
if IsStrEmpty(nmspcSH) then begin
nmspcSH := 'ns' + IntToStr(NextNameSpaceCounter());
AddScopeAttribute('xmlns:'+nmspcSH, sXSI_NS);
end else begin
nmspcSH := Copy(nmspcSH,Length('xmlns:')+1,MaxInt);
end;
GetCurrentScopeObject().SetAttribute(nmspcSH + ':' + sNIL,'true');
end;
function TSOAPBaseFormatter.IsCurrentScopeNil(): Boolean;
Var
s,nsShortName,nilName : shortstring;
begin
CheckScope();
nsShortName := FindAttributeByValueInScope(sXSI_NS);
Result := False;
if IsStrEmpty(nsShortName) then begin
nilName := 'nil';
end else begin
nsShortName := Copy(nsShortName,1 + Pos(':',nsShortName),MaxInt);
if not IsStrEmpty(nsShortName) Then
nsShortName := nsShortName + ':';
nilName := nsShortName + 'nil';
end;
s := Trim(GetCurrentScopeObject().GetAttribute(nilName));
if ( Length(s) > 0 ) and ( AnsiSameText(s,'true') or AnsiSameText(s,'"true"') ) then begin
Result := True;
end;
end;
procedure TSOAPBaseFormatter.BeginScope(
Const AScopeName,ANameSpace : string;
Const ANameSpaceShortName : string;
Const AScopeType : TScopeType;
const AStyle : TArrayStyle
);
Var
nsStr, scpStr : String;
e : TDOMElement;
hasNmspc, addAtt : Boolean;
begin
if ( AScopeType = stObject ) or
( ( AScopeType = stArray ) and ( AStyle = asScoped ) )
then begin
scpStr := AScopeName;
hasNmspc := Not IsStrEmpty(ANameSpace);
If hasNmspc Then Begin
nsStr := FindAttributeByValueInScope(ANameSpace);
addAtt := IsStrEmpty(nsStr);
If addAtt Then Begin
If IsStrEmpty(ANameSpaceShortName) Then
nsStr := 'ns' + IntToStr(NextNameSpaceCounter())
Else
nsStr := Trim(ANameSpaceShortName);
End Else Begin
nsStr := Copy(nsStr,Succ(AnsiPos(':',nsStr)),MaxInt);
End;
scpStr := nsStr + ':' + scpStr;
End;
e := FDoc.CreateElement(scpStr);
If HasScope() Then
GetCurrentScopeObject().AppendChild(e)
Else
FDoc.AppendChild(e);
if ( AScopeType = stObject ) then begin
PushStack(e);
end else begin
PushStack(e,AStyle,'');
end;
if hasNmspc and addAtt then begin
e.SetAttribute('xmlns:'+nsStr,ANameSpace);
StackTop().SetNameSpace(ANameSpace);
end;
end else if ( ( AScopeType = stArray ) and ( AStyle = asEmbeded ) ) then begin
StackTop().BeginEmbeddedScope();
end;
end;
function TSOAPBaseFormatter.InternalBeginScopeRead(
var AScopeName : string;
const ATypeInfo : PTypeInfo;
const AScopeType : TScopeType;
const AStyle : TArrayStyle;
const AItemName : string
): Integer;
var
locNode : TDOMNode;
stk : TStackItem;
typData : TTypeRegistryItem;
nmspc,nmspcSH : string;
strNodeName : string;
begin
if ( Style = Document ) then begin
typData := GetTypeRegistry().Find(ATypeInfo,False);
if not Assigned(typData) then begin
Error('Object type not registered : %s',[IfThen(Assigned(ATypeInfo),ATypeInfo^.Name,'')]);
end;
nmspc := typData.NameSpace;
if IsStrEmpty(nmspc) then begin
nmspcSH := ''
end else begin
nmspcSH := FindAttributeByValueInScope(nmspc);
if not IsStrEmpty(nmspcSH) then begin
nmspcSH := Copy(nmspcSH,Length('xmlns:')+1,MaxInt);
end;
end;
if IsStrEmpty(nmspcSH) then begin
strNodeName := AScopeName
end else begin
if ( Pos(':',AScopeName) < 1 ) then begin
strNodeName := nmspcSH + ':' + AScopeName
end else begin
strNodeName := AScopeName;
end;
end;
end else begin
nmspcSH := '';
strNodeName := AScopeName;
end;
stk := StackTop();
if ( AScopeType = stObject ) or
( ( AScopeType = stArray ) and ( AStyle = asScoped ) )
then begin
locNode := stk.FindNode(strNodeName);
end else begin
locNode := stk.ScopeObject;
end;
if ( locNode = nil ) then begin
Result := -1;
end else begin
if ( AScopeType = stObject ) then begin
PushStack(locNode);
end else begin
PushStack(locNode,AStyle,AItemName);
end;
if ( Style = Document ) then begin
StackTop().SetNameSpace(nmspc);
end;
Result := StackTop().GetItemsCount();
end;
end;
procedure TSOAPBaseFormatter.SetSerializationStyle(const ASerializationStyle: TSerializationStyle);
begin
FSerializationStyle := ASerializationStyle;
end;
function TSOAPBaseFormatter.GetSerializationStyle(): TSerializationStyle;
begin
Result := FSerializationStyle;
end;
procedure TSOAPBaseFormatter.SetStyleAndEncoding(
const AStyle: TSOAPDocumentStyle;
const AEncoding: TSOAPEncodingStyle
);
begin
FKeepedStyle := Style;
FKeepedEncoding := EncodingStyle;
Style := AStyle;
EncodingStyle := AEncoding;
end;
procedure TSOAPBaseFormatter.RestoreStyleAndEncoding();
begin
EncodingStyle := FKeepedEncoding;
Style := FKeepedStyle;
end;
procedure TSOAPBaseFormatter.Prepare();
var
locDoc : TwstXMLDocument;
begin
locDoc := GetXmlDoc();
if Assigned(locDoc.DocumentElement) and
AnsiSameText(locDoc.DocumentElement.NodeName,( sSOAP_ENV_ABR + ':' + sENVELOPE ))
then begin
ClearStack();
PushStack(locDoc.DocumentElement);
end else begin
BeginScope(sENVELOPE,sSOAP_ENV,sSOAP_ENV_ABR,stObject,asNone);
AddScopeAttribute('xmlns:xsi',sXSI_NS);
AddScopeAttribute('xmlns:'+sXSD, sXSD_NS);
AddScopeAttribute('xmlns:'+sSOAP_ENC_ABR, sSOAP_ENC);
end;
end;
function TSOAPBaseFormatter.ReadHeaders(ACallContext: ICallContext): Integer;
function ExtractTypeInfo(ANode : TDOMElement) : TTypeRegistryItem;
var
j : Integer;
ndName, nsSN, nsLN, s : string;
begin
ndName := ANode.NodeName;
j := Pos(':',ndName);
if ( j > 0 ) then
nsSN := Copy(ndName,1,Pred(j))
else
nsSN := '';
if IsStrEmpty(nsSN) then
s := sXML_NS
else
s := sXML_NS + ':' + nsSN;
nsLN := FindAttributeByNameInScope(s);
Result := GetTypeRegistry().FindByDeclaredName(Copy(ndName,Succ(j),MaxInt),nsLN);
end;
var
i : Integer;
nd : TDOMElement;
typItm : TTypeRegistryItem;
tmpObj : THeaderBlock;
locName : string;
chdLst : TDOMNodeList;
begin
SetStyleAndEncoding(Document,Literal);
try
Result := StackTop().ItemsCount;
if ( Result > 0 ) then begin
chdLst := StackTop().ScopeObject.ChildNodes;
try
for i := 0 to Pred(Result) do begin
nd := chdLst.Item[i] as TDOMElement;
typItm := ExtractTypeInfo(nd);
if Assigned(typItm) then begin
if ( typItm.DataType^.Kind = tkClass ) then begin
tmpObj := nil;
locName := nd.NodeName;
Get(typItm.DataType,locName,tmpObj);
if Assigned(tmpObj) then begin
tmpObj.Direction := hdIn;
ACallContext.AddHeader(tmpObj,True);
end;
end;
end;
end;
finally
ReleaseDomNode(chdLst);
end;
end;
finally
RestoreStyleAndEncoding();
end;
end;
function TSOAPBaseFormatter.WriteHeaders(ACallContext : ICallContext): Integer;
var
ptyp : PTypeInfo;
h : THeaderBlock;
i, c : Integer;
begin
Result := ACallContext.GetHeaderCount([hdOut]);
if ( Result > 0 ) then begin
BeginHeader();
try
c := ACallContext.GetHeaderCount(AllHeaderDirection);
for i := 0 to Pred(c) do begin
h := ACallContext.GetHeader(i);
if ( h.Direction = hdOut ) then begin
ptyp := PTypeInfo(h.ClassInfo);
Put(GetTypeRegistry().ItemByTypeInfo[ptyp].DeclaredName,ptyp,h);
end;
end;
finally
EndHeader();
end;
end;
end;
procedure TSOAPBaseFormatter.EndScope();
begin
CheckScope();
if ( StackTop().EmbeddedScopeCount = 0 ) then begin
FStack.Pop().Free();
end else begin
StackTop().EndEmbeddedScope();
end;
end;
procedure TSOAPBaseFormatter.AddScopeAttribute(const AName, AValue: string);
begin
CheckScope();
GetCurrentScopeObject().SetAttribute(AName,AValue);
end;
procedure TSOAPBaseFormatter.Put(
const AName: String;
const ATypeInfo: PTypeInfo;
const AData
);
Var
int64Data : Int64;
strData : string;
objData : TObject;
boolData : Boolean;
enumData : TEnumIntType;
floatDt : Extended;
begin
Case ATypeInfo^.Kind Of
tkInt64{$IFDEF FPC},tkQWord{$ENDIF} :
Begin
int64Data := Int64(AData);
PutInt64(AName,ATypeInfo,int64Data);
End;
tkLString{$IFDEF FPC},tkAString{$ENDIF} :
Begin
strData := String(AData);
PutStr(AName,ATypeInfo,strData);
End;
tkClass :
Begin
objData := TObject(AData);
PutObj(AName,ATypeInfo,objData);
End;
tkRecord :
begin
PutRecord(AName,ATypeInfo,Pointer(@AData));
end;
{$IFDEF FPC}
tkBool :
Begin
boolData := Boolean(AData);
PutBool(AName,ATypeInfo,boolData);
End;
{$ENDIF}
tkInteger, tkEnumeration :
begin
{$IFNDEF FPC}
if ( ATypeInfo^.Kind = tkEnumeration ) and
( GetTypeData(ATypeInfo)^.BaseType^ = TypeInfo(Boolean) )
then begin
boolData := Boolean(AData);
PutBool(AName,ATypeInfo,boolData);
end else begin
{$ENDIF}
enumData := 0;
Case GetTypeData(ATypeInfo)^.OrdType Of
otSByte : enumData := ShortInt(AData);
otUByte : enumData := Byte(AData);
otSWord : enumData := SmallInt(AData);
otUWord : enumData := Word(AData);
otSLong,
otULong : enumData := LongInt(AData);
End;
If ( ATypeInfo^.Kind = tkInteger ) Then
PutInt64(AName,ATypeInfo,enumData)
Else
PutEnum(AName,ATypeInfo,enumData);
{$IFNDEF FPC}
end;
{$ENDIF}
end;
tkFloat :
Begin
floatDt := 0;
Case GetTypeData(ATypeInfo)^.FloatType Of
ftSingle : floatDt := Single(AData);
ftDouble : floatDt := Double(AData);
ftExtended : floatDt := Extended(AData);
ftCurr : floatDt := Currency(AData);
ftComp : floatDt := Comp(AData);
End;
PutFloat(AName,ATypeInfo,floatDt);
End;
End;
end;
procedure TSOAPBaseFormatter.PutScopeInnerValue(
const ATypeInfo : PTypeInfo;
const AData
);
Var
int64SData : Int64;
{$IFDEF FPC}
int64UData : QWord;
boolData : Boolean;
{$ENDIF}
strData : string;
enumData : TEnumIntType;
floatDt : Extended;
dataBuffer : string;
frmt : string;
prcsn,i : Integer;
begin
CheckScope();
Case ATypeInfo^.Kind Of
tkInt64 :
begin
int64SData := Int64(AData);
dataBuffer := IntToStr(int64SData);
end;
{$IFDEF FPC}
tkQWord :
begin
int64UData := QWord(AData);
dataBuffer := IntToStr(int64UData);
end;
{$ENDIF}
tkLString{$IFDEF FPC},tkAString{$ENDIF} :
begin
strData := string(AData);
dataBuffer := strData;
end;
tkClass :
begin
raise ESOAPException.Create('Inner Scope value must be a "simple type" value.');
end;
{$IFDEF FPC}
tkBool :
begin
boolData := Boolean(AData);
dataBuffer := BoolToStr(boolData);
end;
{$ENDIF}
tkInteger :
begin
case GetTypeData(ATypeInfo)^.OrdType of
otSByte : enumData := ShortInt(AData);
otUByte : enumData := Byte(AData);
otSWord : enumData := SmallInt(AData);
otUWord : enumData := Word(AData);
otSLong,
otULong : enumData := LongInt(AData);
end;
dataBuffer := IntToStr(enumData);
end;
tkEnumeration :
begin
enumData := 0;
case GetTypeData(ATypeInfo)^.OrdType of
otSByte : enumData := ShortInt(AData);
otUByte : enumData := Byte(AData);
otSWord : enumData := SmallInt(AData);
otUWord : enumData := Word(AData);
otSLong,
otULong : enumData := LongInt(AData);
end;
dataBuffer := GetTypeRegistry().ItemByTypeInfo[ATypeInfo].GetExternalPropertyName(GetEnumName(ATypeInfo,enumData))
end;
tkFloat :
begin
floatDt := 0;
case GetTypeData(ATypeInfo)^.FloatType of
ftSingle :
begin
floatDt := Single(AData);
prcsn := 7;
end;
ftDouble :
begin
floatDt := Double(AData);
prcsn := 15;
end;
ftExtended :
begin
floatDt := Extended(AData);
prcsn := 15;
end;
ftCurr :
begin
floatDt := Currency(AData);
prcsn := 7;
end;
ftComp :
begin
floatDt := Comp(AData);
prcsn := 7;
end;
end;
frmt := '#.' + StringOfChar('#',prcsn) + 'E-0';
dataBuffer := FormatFloat(frmt,floatDt);
i := Pos(',',dataBuffer);
if ( i > 0 ) then
dataBuffer[i] := '.';
end;
end;
StackTop().ScopeObject.AppendChild(FDoc.CreateTextNode(dataBuffer));
end;
procedure TSOAPBaseFormatter.Get(
const ATypeInfo : PTypeInfo;
var AName : String;
var AData
);
Var
int64Data : Int64;
strData : string;
objData : TObject;
boolData : Boolean;
enumData : TEnumIntType;
floatDt : Extended;
recObject : Pointer;
begin
Case ATypeInfo^.Kind Of
tkInt64{$IFDEF FPC},tkQWord{$ENDIF} :
Begin
int64Data := 0;
GetInt64(ATypeInfo,AName,int64Data);
Int64(AData) := int64Data;
End;
tkLString{$IFDEF FPC},tkAString{$ENDIF} :
Begin
strData := '';
GetStr(ATypeInfo,AName,strData);
String(AData) := strData;
End;
tkClass :
Begin
objData := TObject(AData);
GetObj(ATypeInfo,AName,objData);
TObject(AData) := objData;
End;
tkRecord :
begin
recObject := Pointer(@AData);
GetRecord(ATypeInfo,AName,recObject);
end;
{$IFDEF FPC}
tkBool :
Begin
boolData := False;
GetBool(ATypeInfo,AName,boolData);
Boolean(AData) := boolData;
End;
{$ENDIF}
tkInteger, tkEnumeration :
begin
{$IFNDEF FPC}
if ( ATypeInfo^.Kind = tkEnumeration ) and
( GetTypeData(ATypeInfo)^.BaseType^ = TypeInfo(Boolean) )
then begin
boolData := False;
GetBool(ATypeInfo,AName,boolData);
Boolean(AData) := boolData;
end else begin
{$ENDIF}
enumData := 0;
If ( ATypeInfo^.Kind = tkInteger ) Then
GetInt64(ATypeInfo,AName,enumData)
Else
GetEnum(ATypeInfo,AName,enumData);
Case GetTypeData(ATypeInfo)^.OrdType Of
otSByte : ShortInt(AData) := enumData;
otUByte : Byte(AData) := enumData;
otSWord : SmallInt(AData) := enumData;
otUWord : Word(AData) := enumData;
otSLong,
otULong : LongInt(AData) := enumData;
End;
{$IFNDEF FPC}
end;
{$ENDIF}
end;
tkFloat :
Begin
floatDt := 0;
GetFloat(ATypeInfo,AName,floatDt);
Case GetTypeData(ATypeInfo)^.FloatType Of
ftSingle : Single(AData) := floatDt;
ftDouble : Double(AData) := floatDt;
ftExtended : Extended(AData) := floatDt;
ftCurr : Currency(AData) := floatDt;
{$IFDEF CPU86}
ftComp : Comp(AData) := floatDt;
{$ENDIF}
End;
End;
End;
end;
procedure TSOAPBaseFormatter.GetScopeInnerValue(
const ATypeInfo : PTypeInfo;
var AData
);
Var
enumData : TEnumIntType;
floatDt : Extended;
dataBuffer : string;
nd : TDOMNode;
begin
CheckScope();
nd := StackTop().ScopeObject;
if nd.HasChildNodes() then
dataBuffer := nd.FirstChild.NodeValue
else
dataBuffer := StackTop().ScopeObject.NodeValue;
Case ATypeInfo^.Kind Of
tkInt64 : Int64(AData) := StrToInt64Def(Trim(dataBuffer),0);
{$IFDEF FPC}
tkQWord : QWord(AData) := StrToInt64Def(Trim(dataBuffer),0);
{$ENDIF}
tkLString{$IFDEF FPC},tkAString{$ENDIF} : string(AData) := dataBuffer;
tkClass :
begin
raise ESOAPException.Create('Inner Scope value must be a "simple type" value.');
end;
{$IFDEF FPC}
tkBool :
begin
dataBuffer := LowerCase(Trim(dataBuffer));
if IsStrEmpty(dataBuffer) then
Boolean(AData) := False
else
Boolean(AData) := StrToBool(dataBuffer);
end;
{$ENDIF}
tkInteger, tkEnumeration :
begin
if ( ATypeInfo^.Kind = tkInteger ) then
enumData := StrToIntDef(Trim(dataBuffer),0)
else
enumData := GetEnumValue(ATypeInfo,GetTypeRegistry().ItemByTypeInfo[ATypeInfo].GetInternalPropertyName(dataBuffer));
case GetTypeData(ATypeInfo)^.OrdType of
otSByte : ShortInt(AData) := enumData;
otUByte : Byte(AData) := enumData;
otSWord : SmallInt(AData) := enumData;
otUWord : Word(AData) := enumData;
otSLong,
otULong : LongInt(AData) := enumData;
end;
end;
tkFloat :
begin
{$IFDEF FPC}
{$IFDEF FPC_211}
floatDt := StrToFloatDef(Trim(dataBuffer),0,wst_FormatSettings);
{$ELSE}
floatDt := StrToFloatDef(Trim(dataBuffer),0);
{$ENDIF}
{$ELSE}
floatDt := StrToFloatDef(Trim(dataBuffer),0,wst_FormatSettings);
{$ENDIF}
case GetTypeData(ATypeInfo)^.FloatType of
ftSingle : Single(AData) := floatDt;
ftDouble : Double(AData) := floatDt;
ftExtended : Extended(AData) := floatDt;
ftCurr : Currency(AData) := floatDt;
{$IFDEF CPU86}
ftComp : Comp(AData) := floatDt;
{$ENDIF}
end;
end;
end;
end;
function TSOAPBaseFormatter.ReadBuffer (const AName : string ) : string;
Var
locElt : TDOMNode;
namespaceShortName, strNodeName, s : string;
begin
strNodeName := AName;
if ( Style = Document ) then begin
namespaceShortName := Copy(FindAttributeByValueInScope(StackTop().NameSpace),AnsiPos(':',namespaceShortName) + 1,MaxInt);
if not IsStrEmpty(namespaceShortName) then begin
s := ExtractNameSpaceShortName(namespaceShortName);
if not IsStrEmpty(s) then
strNodeName := s + ':' + strNodeName;
end;
end;
if ( FSerializationStyle = ssNodeSerialization ) then begin
locElt := StackTop().FindNode(strNodeName);
end else begin
locElt := GetCurrentScopeObject().GetAttributeNode(strNodeName);
end;
if Assigned(locElt) then begin
Result := NodeToBuffer(locElt);
end else begin
Error('Param or Attribute not found : "%s"',[AName]);
end;
end;
procedure TSOAPBaseFormatter.SaveToStream(AStream: TStream);
begin
WriteXMLFile(FDoc,AStream);
end;
procedure TSOAPBaseFormatter.LoadFromStream(AStream: TStream);
Var
nd : TDOMNode;
begin
InternalClear(False);
ReadXMLFile(FDoc,AStream);
nd := GetXmlDoc().DocumentElement;
If Assigned(nd) Then
PushStack(nd);
end;
procedure TSOAPBaseFormatter.Error(const AMsg: string);
begin
Raise ESOAPException.Create(AMsg);
end;
procedure TSOAPBaseFormatter.Error(const AMsg: string;const AArgs: array of const);
begin
Raise ESOAPException.CreateFmt(AMsg,AArgs);
end;
{ TScopedArrayStackItem }
function TScopedArrayStackItem.CreateList(const ANodeName : string): TDOMNodeList;
begin
if ScopeObject.HasChildNodes() then begin
Result := ScopeObject.ChildNodes;
end else begin
Result := nil;
end;
end;
{ TEmbeddedArrayStackItem }
function TEmbeddedArrayStackItem.CreateList(const ANodeName: string): TDOMNodeList;
begin
if ScopeObject.HasChildNodes() then begin
{$IFNDEF FPC}
Result := FilterList(ScopeObject.childNodes,ANodeName);
{$ELSE}
Result := {$IFNDEF FPC_211}TDOMNodeList{$ELSE}TDOMElementList{$ENDIF}.Create(ScopeObject,ANodeName);
{$ENDIF}
end else begin
Result := nil;
end;
end;
end.