123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- unit odatabase;
- {$mode objfpc}{$H+}
- interface
- uses
- TypInfo,Classes, SysUtils, fpjson, restbase;
- Type
- TInt16 = Type Smallint;
- TInt32 = Type Integer;
- SByte = Type Shortint;
- TTimeOfDay = Type TDateTime;
- TDateTimeOffset = Type TDateTime;
- TGUIDString = Type string;
- TBinary = Array of Byte;
- TDuration = type string;
- { TGeography }
- TGeography = Class(TBaseObject)
- private
- FType: String;
- Public
- Class function AllowAdditionalProperties: Boolean; override;
- Published
- Property _type : String Read FType Write FType;
- end;
- { TGeographyPoint }
- TGeographyPoint = Class(TGeography)
- private
- FCoordinates: TDoubleArray;
- Procedure SetCoordinates(AIndex : integer; AValue : TDoubleArray);
- Published
- Property coordinates : TDoubleArray Index 8 Read FCoordinates Write SetCoordinates;
- end;
- TDoubleArrayArray = Array of TDoubleArray;
- { TGeographyLineString }
- TGeographyLineString = Class(TGeography)
- private
- FCoordinates: TDoubleArrayArray;
- Published
- Property coordinates : TDoubleArrayArray Read FCoordinates Write FCoordinates;
- end;
- TGeographyPolygon = Class(TGeography)
- end;
- TGeographyMultiPoint = Class(TGeography)
- end;
- TGeographyMultiLineString = Class(TGeography)
- end;
- TSByteArray = Array of SByte;
- TByteArray = Array of Byte;
- TInt32Array = Array of TInt32;
- TInt16Array = Array of TInt16;
- TDurationArray = Array of TDuration;
- TDateArray = Array of TDate;
- TTimeArray = Array of TTime;
- TTimeOfDayArray = Array of TTimeOfDay;
- TDateTimeOffsetArray = Array of TDateTimeOffset;
- TGUIDStringArray = Array of TGUIDString;
- TBinaryArray = Array of TBinary;
- TGeographyArray = Array of TGeography;
- TGeographyPointArray = Array of TGeographyPoint;
- TGeographyLineStringArray = Array of TGeographyLineString;
- TGeographyPolygonArray = Array of TGeographyPolygon;
- TGeographyMultiPointArray = Array of TGeographyMultiPoint;
- TGeographyMultiLineStringArray = Array of TGeographyMultiLineString;
- TAnnotation = TJSONEnum;
- { TODataObject }
- TODataObject = Class(TBaseObject)
- Private
- FAns : TJSONObject;
- function GetAnnotation(Index : Integer): TAnnotation;
- function GetAnnotationValue(AName : String): TJSONData;
- function GetDataAnnotationCount: Integer;
- Protected
- Procedure AddAnnotation(Const AName : String; AValue : TJSONData);
- Class Function DynArrayToJSONArray(A : Pointer; AType : string; AClassType : TBaseObjectClass = Nil) : TJSONArray;
- Class Function JSONArrayToDynArray(A : TJSONArray; AType : string; AClassType : TBaseObjectClass = Nil) : Pointer;
- Public
- Destructor Destroy; override;
- Procedure LoadPropertyFromJSON(Const AName : String; JSON : TJSONData); override;
- Class Function MakeKeyString(Const AKey : String) : String;
- Class Function AllowAdditionalProperties : Boolean; override;
- Property ODataAnnotations[Index : Integer] : TAnnotation Read GetAnnotation;
- Property ODataAnnotationValues[AName : String] : TJSONData Read GetAnnotationValue;
- Property ODataAnnotationCount : Integer Read GetDataAnnotationCount;
- end;
- TODataObjectClass = Class of TODataObject;
- TODataObjectArray = Array of TODataObject;
- TODataComplexType = Class(TODataObject);
- TODataComplexTypeClass = Class of TODataComplexType;
- { TODataError }
- TODataErrorDetail = Record
- Code : String;
- Message : String;
- Target : String;
- end;
- TODataErrorDetails = Array of TODataErrorDetail;
- TODataError = Class(TObject)
- private
- FCode: String;
- FDetails: TODataErrorDetails;
- FInnerError: String;
- FMessage: String;
- FTargetCode: String;
- Public
- Property Code : String Read FCode Write FCode;
- Property Message : String Read FMessage Write FMessage;
- Property Target : String Read FTargetCode Write FTargetCode;
- Property Details : TODataErrorDetails Read FDetails Write FDetails;
- // JSON
- Property InnerError : String Read FInnerError Write FInnerError;
- end;
- { EOData }
- EOData =Class(Exception)
- private
- FError: TODataError;
- FStatusCode: Integer;
- FStatusText: String;
- Public
- Destructor Destroy; override;
- Property StatusCode : Integer Read FStatusCode Write FStatusCode;
- Property StatusText : String Read FStatusText Write FStatusText;
- Property Error : TODataError Read FError Write FError;
- end;
- Function BinaryToString(B : TBinary) : String;
- implementation
- Function BinaryToString(B : TBinary) : String;
- Var
- E : Byte;
- begin
- Result:='';
- For E in B do
- Result:=Result+HexStr(E,2);
- end;
- { TGeographyPoint }
- Procedure TGeographyPoint.SetCoordinates(AIndex: integer; AValue: TDoubleArray);
- Var
- D : Double;
- begin
- { Writeln('Setting coordinates');
- For d in AValue do
- writeln('Got ',D);}
- FCoordinates:=AValue;
- end;
- { TGeography }
- Class function TGeography.AllowAdditionalProperties: Boolean;
- begin
- Result:=True;
- end;
- { EOData }
- Destructor EOData.Destroy;
- begin
- FreeAndNil(FError);
- inherited Destroy;
- end;
- { TODataObject }
- function TODataObject.GetAnnotation(Index : Integer): TAnnotation;
- begin
- If Not Assigned(FAns) or (Index<0) or (Index>=FAns.Count) then
- begin
- Result.Key:='';
- Result.KeyNum:=-1;
- Result.Value:=Nil;
- end
- else
- begin
- Result.Key:=FAns.Names[Index];
- Result.KeyNum:=Index;
- Result.Value:=FAns.Items[Index];
- end;
- end;
- function TODataObject.GetAnnotationValue(AName : String): TJSONData;
- Var
- I : Integer;
- begin
- Result:=Nil;
- if Assigned(FAns) then
- begin
- I:=FAns.IndexOfName(AName);
- if I<>-1 then
- Result:=FAns.Items[i];
- end;
- end;
- function TODataObject.GetDataAnnotationCount: Integer;
- begin
- if Assigned(FAns) then
- Result:=FAns.Count
- else
- Result:=0;
- end;
- Procedure TODataObject.AddAnnotation(Const AName: String; AValue: TJSONData);
- begin
- If Not Assigned(FAns) then
- FAns:=TJSONObject.Create();
- FAns.Add(AName,AValue.Clone);
- end;
- Type
- TShortIntArray = Array of ShortInt;
- TSmallIntArray = Array of SmallInt;
- TWordArray = Array of Word;
- TCardinalArray = Array of Cardinal;
- TQWordArray= Array of QWord;
- TSingleArray = Array of Single;
- Class Function TODataObject.DynArrayToJSONArray(A: Pointer; AType: string; AClassType : TBaseObjectClass = Nil): TJSONArray;
- Var
- I,L : Integer;
- begin
- Result:=TJSONArray.Create;
- L:=Length(TByteArray(A));
- Case LowerCase(aType) of
- 'boolean':
- For I:=0 to L-1 do
- Result.Add(TBooleanArray(A)[i]);
- 'byte',
- 'tsbyte':
- For I:=0 to L-1 do
- Result.Add(TByteArray(A)[i]);
- 'shortint':
- For I:=0 to L-1 do
- Result.Add(TShortIntArray(A)[i]);
- 'int16',
- 'tint16',
- 'smallint':
- For I:=0 to L-1 do
- Result.Add(TSmallIntArray(A)[i]);
- 'word':
- For I:=0 to L-1 do
- Result.Add(TWordArray(A)[i]);
- 'tint32',
- 'int32',
- 'integer':
- For I:=0 to L-1 do
- Result.Add(TIntegerArray(A)[i]);
- 'cardinal',
- 'dword':
- For I:=0 to L-1 do
- Result.Add(TCardinalArray(A)[i]);
- 'tint64',
- 'int64':
- For I:=0 to L-1 do
- Result.Add(TInt64Array(A)[i]);
- 'qword':
- For I:=0 to L-1 do
- {$IFNDEF VER2_6}
- Result.Add(TQWordArray(A)[i]);
- {$else}
- Result.Add(TInt64Array(A)[i]);
- {$ENDIF}
- 'string':
- For I:=0 to L-1 do
- Result.Add(TStringArray(A)[i]);
- 'tguidstring':
- For I:=0 to L-1 do
- Result.Add(TStringArray(A)[i]);
- 'double':
- For I:=0 to L-1 do
- Result.Add(TDoubleArray(A)[i]);
- 'single':
- For I:=0 to L-1 do
- Result.Add(TSingleArray(A)[i]);
- else
- if Pos('array',lowerCase(atype))<>0 then
- Raise EOData.Create('Cannot convert array of array: '+atype);
- if (AClassType=Nil) then
- Raise EOData.Create('Cannot convert array of object without class type');
- For I:=0 to L-1 do
- if (TObjectArray(A)[i].InheritsFrom(AClassType)) then
- Result.Add(TObjectArray(A)[i].SaveToJSON);
- end;
- end;
- Class Function TODataObject.JSONArrayToDynArray(A: TJSONArray; AType: string; AClassType : TBaseObjectClass = Nil ): Pointer;
- Var
- I,L : Integer;
- begin
- Result:=TJSONArray.Create;
- L:=A.Count;
- Case LowerCase(aType) of
- 'boolean':
- begin
- SetLength(TBooleanArray(Result),L);
- For I:=0 to L-1 do
- TBooleanArray(Result)[i]:=A.Booleans[i];
- end;
- 'byte',
- 'tsbyte':
- begin
- SetLength(TByteArray(Result),L);
- For I:=0 to L-1 do
- TByteArray(Result)[i]:=A.Integers[i];
- end;
- 'shortint':
- begin
- SetLength(TShortIntArray(Result),L);
- For I:=0 to L-1 do
- TShortIntArray(Result)[i]:=A.Integers[i];
- end;
- 'int16',
- 'tint16',
- 'smallint':
- begin
- SetLength(TSmallIntArray(Result),L);
- For I:=0 to L-1 do
- TSmallIntArray(Result)[i]:=A.Integers[i];
- end;
- 'word':
- begin
- SetLength(TWordArray(Result),L);
- For I:=0 to L-1 do
- TWordArray(Result)[i]:=A.Integers[i];
- end;
- 'tint32',
- 'int32',
- 'integer':
- begin
- SetLength(TIntegerArray(Result),L);
- For I:=0 to L-1 do
- TIntegerArray(Result)[i]:=A.Integers[i];
- end;
- 'cardinal',
- 'dword':
- begin
- SetLength(TCardinalArray(Result),L);
- For I:=0 to L-1 do
- TCardinalArray(Result)[i]:=A.Integers[i];
- end;
- 'tint64',
- 'int64':
- begin
- SetLength(TInt64Array(Result),L);
- For I:=0 to L-1 do
- TInt64Array(Result)[i]:=A.Int64s[i];
- end;
- 'qword':
- begin
- SetLength(TQWordArray(Result),L);
- For I:=0 to L-1 do
- {$IFDEF VER2_6}
- TInt64Array(Result)[i]:=A.Int64s[i];
- {$ELSE}
- TQWordArray(Result)[i]:=A.QWords[i];
- {$ENDIF}
- end;
- 'tstring',
- 'string':
- begin
- SetLength(TStringArray(Result),L);
- For I:=0 to L-1 do
- TStringArray(Result)[i]:=A.Strings[i];
- end;
- 'guidstring',
- 'tguidstring':
- begin
- SetLength(TStringArray(Result),L);
- For I:=0 to L-1 do
- TStringArray(Result)[i]:=A.Strings[i];
- end;
- 'double':
- begin
- SetLength(TDoubleArray(Result),L);
- For I:=0 to L-1 do
- TDoubleArray(Result)[i]:=A.Floats[i];
- end;
- 'single':
- begin
- SetLength(TSingleArray(Result),L);
- For I:=0 to L-1 do
- TSingleArray(Result)[i]:=A.Floats[i];
- end;
- else
- if (Pos('array',lowercase(atype))<>0) then
- Raise EOData.Create('Cannot convert array of array: '+atype);
- if (AClassType=Nil) then
- Raise EOData.Create('Cannot convert array of object without class type');
- SetLength(TObjectArray(Result),L);
- For I:=0 to L-1 do
- begin
- if A.Types[i]<>jtObject then
- Raise EOData.CreateFmt('Element %d of array is not an object: %s',[I,A.Items[i].AsJSON]);
- TObjectArray(Result)[i]:=AClassType.Create;
- TObjectArray(Result)[i].LoadFromJSON(A.Objects[i]);
- end;
- end;
- end;
- Destructor TODataObject.Destroy;
- begin
- FreeAndNil(FAns);
- Inherited;
- end;
- Procedure TODataObject.LoadPropertyFromJSON(Const AName: String; JSON: TJSONData
- );
- begin
- if (AName<>'') and (AName[1]='@') then
- AddAnnotation(AName,JSON)
- else
- inherited LoadPropertyFromJSON(AName, JSON);
- end;
- Class Function TODataObject.MakeKeyString(Const AKey: String): String;
- begin
- Result:=''''+AKey+'''';
- end;
- Class Function TODataObject.AllowAdditionalProperties: Boolean;
- begin
- Result:=True; // So we catch annnotations
- end;
- end.
|