|
@@ -48,19 +48,13 @@ Const
|
|
IndexShift = 3; // Number of bits reserved for flags.
|
|
IndexShift = 3; // Number of bits reserved for flags.
|
|
|
|
|
|
Type
|
|
Type
|
|
-{$M+}
|
|
|
|
|
|
+{$TYPEINFO ON}
|
|
|
|
|
|
TBaseObject = CLass(TObject)
|
|
TBaseObject = CLass(TObject)
|
|
Private
|
|
Private
|
|
FObjectOptions : TObjectOptions;
|
|
FObjectOptions : TObjectOptions;
|
|
fadditionalProperties : TJSONObject;
|
|
fadditionalProperties : TJSONObject;
|
|
FBits : TBits;
|
|
FBits : TBits;
|
|
-
|
|
|
|
-{ #todo -oWayneSherman : can the next two private methods be removed and instead
|
|
|
|
- use the rtl provided GetDynArrayProp / SetDynArrayProp in TypInfo.pp unit }
|
|
|
|
- Function GetDynArrayProp(P: PPropInfo) : Pointer; virtual;
|
|
|
|
- procedure SetDynArrayProp(P: PPropInfo; AValue : Pointer); virtual;
|
|
|
|
-
|
|
|
|
procedure SetObjectOptions(AValue: TObjectOptions);
|
|
procedure SetObjectOptions(AValue: TObjectOptions);
|
|
Function GetAdditionalProperties : TJSONObject;
|
|
Function GetAdditionalProperties : TJSONObject;
|
|
protected
|
|
protected
|
|
@@ -152,8 +146,6 @@ Type
|
|
Property Objects [Aindex : Integer] : TBaseObject Read GetO Write SetO; default;
|
|
Property Objects [Aindex : Integer] : TBaseObject Read GetO Write SetO; default;
|
|
end;
|
|
end;
|
|
|
|
|
|
- { TBaseObjectList }
|
|
|
|
-
|
|
|
|
{ TBaseNamedObjectList }
|
|
{ TBaseNamedObjectList }
|
|
|
|
|
|
TBaseNamedObjectList = Class(TBaseObject)
|
|
TBaseNamedObjectList = Class(TBaseObject)
|
|
@@ -438,6 +430,7 @@ begin
|
|
Result:=CreateObject(AKind);
|
|
Result:=CreateObject(AKind);
|
|
ObjectByName[AName]:=Result;
|
|
ObjectByName[AName]:=Result;
|
|
end;
|
|
end;
|
|
|
|
+
|
|
{ TJSONSchema }
|
|
{ TJSONSchema }
|
|
|
|
|
|
Procedure TJSONSchema.SetArrayProperty(P: PPropInfo; AValue: TJSONArray);
|
|
Procedure TJSONSchema.SetArrayProperty(P: PPropInfo; AValue: TJSONArray);
|
|
@@ -525,11 +518,6 @@ end;
|
|
|
|
|
|
{ TBaseObject }
|
|
{ TBaseObject }
|
|
|
|
|
|
-function TBaseObject.GetDynArrayProp(P: PPropInfo): Pointer;
|
|
|
|
-begin
|
|
|
|
- Result:=Pointer(GetObjectProp(Self,P));
|
|
|
|
-end;
|
|
|
|
-
|
|
|
|
{ $DEFINE DUMPARRAY}
|
|
{ $DEFINE DUMPARRAY}
|
|
|
|
|
|
{$IFDEF DUMPARRAY}
|
|
{$IFDEF DUMPARRAY}
|
|
@@ -554,19 +542,20 @@ begin
|
|
Writeln(ClassName,' property ',N, ' has ref count ',r^.refcount,' and high ',r^.high);
|
|
Writeln(ClassName,' property ',N, ' has ref count ',r^.refcount,' and high ',r^.high);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
-{$ENDIF}
|
|
|
|
|
|
|
|
-procedure TBaseObject.SetDynArrayProp(P: PPropInfo; AValue: Pointer);
|
|
|
|
|
|
+function GetDynArrayProp(Instance: TObject; PropInfo: PPropInfo): Pointer;
|
|
begin
|
|
begin
|
|
-{$IFDEF DUMPARRAY}
|
|
|
|
- DumpArray(ClassName+' (set)',P^.PropType^.Name,AValue);
|
|
|
|
-{$ENDIF}
|
|
|
|
- SetObjectProp(Self,P,TObject(AValue));
|
|
|
|
-{$IFDEF DUMPARRAY}
|
|
|
|
- DumpArray(ClassName+' (check)',P^.PropType^.Name,AValue);
|
|
|
|
-{$ENDIF}
|
|
|
|
|
|
+ Result := TypInfo.GetDynArrayProp(Instance,PropInfo);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure SetDynArrayProp(Instance: TObject; PropInfo: PPropInfo; const Value: Pointer);
|
|
|
|
+begin
|
|
|
|
+ DumpArray(Instance.ClassName+' (set)',PropInfo^.PropType^.Name,Value);
|
|
|
|
+ TypInfo.SetDynArrayProp(Instance,PropInfo,Value);
|
|
|
|
+ DumpArray(Instance.ClassName+' (check)',PropInfo^.PropType^.Name,Value);
|
|
|
|
+end;
|
|
|
|
+{$ENDIF}
|
|
|
|
+
|
|
procedure TBaseObject.SetObjectOptions(AValue: TObjectOptions);
|
|
procedure TBaseObject.SetObjectOptions(AValue: TObjectOptions);
|
|
begin
|
|
begin
|
|
if FObjectOptions=AValue then Exit;
|
|
if FObjectOptions=AValue then Exit;
|
|
@@ -598,6 +587,10 @@ begin
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TBaseObject.ClearProperty(P: PPropInfo);
|
|
procedure TBaseObject.ClearProperty(P: PPropInfo);
|
|
|
|
+var
|
|
|
|
+ TypeDataPtr: PTypeData;
|
|
|
|
+ ObjectArray: TObjectArray;
|
|
|
|
+ Idx: Integer;
|
|
begin
|
|
begin
|
|
Case P^.PropType^.Kind of
|
|
Case P^.PropType^.Kind of
|
|
tkInteger,
|
|
tkInteger,
|
|
@@ -617,10 +610,27 @@ begin
|
|
tkQWord : SetInt64Prop(Self,P,0);
|
|
tkQWord : SetInt64Prop(Self,P,0);
|
|
tkClass :
|
|
tkClass :
|
|
begin
|
|
begin
|
|
|
|
+ //Writeln(ClassName,' Examining object: ',P^.Name);
|
|
GetObjectProp(Self,P).Free;
|
|
GetObjectProp(Self,P).Free;
|
|
SetObjectProp(Self,P,Nil);
|
|
SetObjectProp(Self,P,Nil);
|
|
- end
|
|
|
|
- { #todo -oWayneSherman : is the tkDynArray type missing here? }
|
|
|
|
|
|
+ end;
|
|
|
|
+ tkDynArray:
|
|
|
|
+ begin
|
|
|
|
+ TypeDataPtr := GetTypeData(P^.PropType);
|
|
|
|
+ if TypeDataPtr^.ElType2^.Kind = tkClass then
|
|
|
|
+ begin
|
|
|
|
+ //if the array is holding any objects, free them
|
|
|
|
+ ObjectArray := TObjectArray(GetDynArrayProp(Self,P));
|
|
|
|
+ {$IFDEF DUMPARRAY}
|
|
|
|
+ DumpArray(ClassName+' (clear)',P^.PropType^.Name,Pointer(ObjectArray));
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ //Writeln(ClassName,' Examining array: ',P^.Name,'Count:',Length(ObjectArray));
|
|
|
|
+ for Idx := Low(ObjectArray) to High(ObjectArray) do
|
|
|
|
+ FreeAndNil(ObjectArray[Idx]);
|
|
|
|
+ end;
|
|
|
|
+ SetLength(ObjectArray, 0);
|
|
|
|
+ SetDynArrayProp(Self,P,nil);
|
|
|
|
+ end;
|
|
else
|
|
else
|
|
// Do nothing
|
|
// Do nothing
|
|
end;
|
|
end;
|
|
@@ -670,18 +680,15 @@ end;
|
|
|
|
|
|
procedure TBaseObject.SetArrayProperty(P: PPropInfo; AValue: TJSONArray);
|
|
procedure TBaseObject.SetArrayProperty(P: PPropInfo; AValue: TJSONArray);
|
|
|
|
|
|
- procedure SetObjectArrayProp(PropAsPtr: Pointer;
|
|
|
|
- const TypeName: ShortString;
|
|
|
|
- const ClassType: TClass;
|
|
|
|
|
|
+ procedure SetObjectArrayProp(const TypeName: ShortString; const ClassType: TClass;
|
|
const JSONArray: TJSONArray);
|
|
const JSONArray: TJSONArray);
|
|
var
|
|
var
|
|
- ObjectArray: TObjectArray;
|
|
|
|
|
|
+ ObjectArray: TObjectArray = nil;
|
|
BaseObject: TBaseObject;
|
|
BaseObject: TBaseObject;
|
|
Idx: Integer;
|
|
Idx: Integer;
|
|
begin
|
|
begin
|
|
- ObjectArray := TObjectArray(PropAsPtr);
|
|
|
|
-
|
|
|
|
- // Free all objects
|
|
|
|
|
|
+ //if the array is holding any objects, free them
|
|
|
|
+ ObjectArray := TObjectArray(GetDynArrayProp(Self,P));
|
|
for Idx := Low(ObjectArray) to High(ObjectArray) do
|
|
for Idx := Low(ObjectArray) to High(ObjectArray) do
|
|
FreeAndNil(ObjectArray[Idx]);
|
|
FreeAndNil(ObjectArray[Idx]);
|
|
|
|
|
|
@@ -692,149 +699,143 @@ procedure TBaseObject.SetArrayProperty(P: PPropInfo; AValue: TJSONArray);
|
|
ObjectArray[Idx] := BaseObject;
|
|
ObjectArray[Idx] := BaseObject;
|
|
BaseObject.LoadFromJSON(JSONArray.Objects[Idx]);
|
|
BaseObject.LoadFromJSON(JSONArray.Objects[Idx]);
|
|
end;
|
|
end;
|
|
|
|
+ SetDynArrayProp(Self,P,Pointer(ObjectArray));
|
|
end;
|
|
end;
|
|
|
|
|
|
- procedure SetFloatArrayProp(PropAsPtr: Pointer;
|
|
|
|
- const JSONArray: TJSONArray);
|
|
|
|
|
|
+ procedure SetFloatArrayProp(const JSONArray: TJSONArray);
|
|
var
|
|
var
|
|
- FloatArray: TFloatArray;
|
|
|
|
|
|
+ FloatArray: TFloatArray = nil;
|
|
Idx: Integer;
|
|
Idx: Integer;
|
|
begin
|
|
begin
|
|
- FloatArray := TFloatArray(PropAsPtr);
|
|
|
|
SetLength(FloatArray, JSONArray.Count);
|
|
SetLength(FloatArray, JSONArray.Count);
|
|
- for Idx := Low(FloatArray) to High(FloatArray) do
|
|
|
|
- FloatArray[Idx] := JSONArray.Floats[Idx];
|
|
|
|
|
|
+ for Idx := Low(FloatArray) to High(FloatArray) do
|
|
|
|
+ FloatArray[Idx] := JSONArray.Floats[Idx];
|
|
|
|
+ SetDynArrayProp(Self,P,Pointer(FloatArray));
|
|
end;
|
|
end;
|
|
|
|
|
|
- procedure SetDateTimeArrayProp(PropAsPtr: Pointer;
|
|
|
|
- const JSONArray: TJSONArray);
|
|
|
|
|
|
+ procedure SetDateTimeArrayProp(const JSONArray: TJSONArray);
|
|
var
|
|
var
|
|
- DateTimeArray: TDateTimeArray;
|
|
|
|
|
|
+ DateTimeArray: TDateTimeArray = nil;
|
|
Idx: Integer;
|
|
Idx: Integer;
|
|
begin
|
|
begin
|
|
- DateTimeArray := TDateTimeArray(PropAsPtr);
|
|
|
|
SetLength(DateTimeArray, JSONArray.Count);
|
|
SetLength(DateTimeArray, JSONArray.Count);
|
|
for Idx := Low(DateTimeArray) to High(DateTimeArray) do
|
|
for Idx := Low(DateTimeArray) to High(DateTimeArray) do
|
|
DateTimeArray[Idx] := RFC3339ToDateTime(JSONArray.Strings[Idx]);
|
|
DateTimeArray[Idx] := RFC3339ToDateTime(JSONArray.Strings[Idx]);
|
|
|
|
+ SetDynArrayProp(Self,P,Pointer(DateTimeArray));
|
|
end;
|
|
end;
|
|
|
|
|
|
- procedure SetInt64ArrayProp(PropAsPtr: Pointer;
|
|
|
|
- const JSONArray: TJSONArray);
|
|
|
|
|
|
+ procedure SetInt64ArrayProp(const JSONArray: TJSONArray);
|
|
var
|
|
var
|
|
- Int64Array: TInt64Array;
|
|
|
|
|
|
+ Int64Array: TInt64Array = nil;
|
|
Idx: Integer;
|
|
Idx: Integer;
|
|
begin
|
|
begin
|
|
- Int64Array := TInt64Array(PropAsPtr);
|
|
|
|
SetLength(Int64Array, JSONArray.Count);
|
|
SetLength(Int64Array, JSONArray.Count);
|
|
for Idx := Low(Int64Array) to High(Int64Array) do
|
|
for Idx := Low(Int64Array) to High(Int64Array) do
|
|
Int64Array[Idx] := JSONArray.Int64s[Idx];
|
|
Int64Array[Idx] := JSONArray.Int64s[Idx];
|
|
|
|
+ SetDynArrayProp(Self,P,Pointer(Int64Array));
|
|
end;
|
|
end;
|
|
|
|
|
|
- procedure SetBooleanArrayProp(PropAsPtr: Pointer;
|
|
|
|
- const JSONArray: TJSONArray);
|
|
|
|
|
|
+ procedure SetBooleanArrayProp(const JSONArray: TJSONArray);
|
|
var
|
|
var
|
|
- BooleanArray: TBooleanArray;
|
|
|
|
|
|
+ BooleanArray: TBooleanArray = nil;
|
|
Idx: Integer;
|
|
Idx: Integer;
|
|
begin
|
|
begin
|
|
- BooleanArray := TBooleanArray(PropAsPtr);
|
|
|
|
SetLength(BooleanArray, JSONArray.Count);
|
|
SetLength(BooleanArray, JSONArray.Count);
|
|
for Idx := Low(BooleanArray) to High(BooleanArray) do
|
|
for Idx := Low(BooleanArray) to High(BooleanArray) do
|
|
BooleanArray[Idx] := JSONArray.Booleans[Idx];
|
|
BooleanArray[Idx] := JSONArray.Booleans[Idx];
|
|
|
|
+ SetDynArrayProp(Self,P,Pointer(BooleanArray));
|
|
end;
|
|
end;
|
|
|
|
|
|
- procedure SetIntegerArrayProp(PropAsPtr: Pointer;
|
|
|
|
- const JSONArray: TJSONArray);
|
|
|
|
|
|
+ procedure SetIntegerArrayProp(const JSONArray: TJSONArray);
|
|
var
|
|
var
|
|
- IntegerArray: TIntegerArray;
|
|
|
|
|
|
+ IntegerArray: TIntegerArray = nil;
|
|
Idx: Integer;
|
|
Idx: Integer;
|
|
begin
|
|
begin
|
|
- IntegerArray := TIntegerArray(PropAsPtr);
|
|
|
|
SetLength(IntegerArray, JSONArray.Count);
|
|
SetLength(IntegerArray, JSONArray.Count);
|
|
for Idx := Low(IntegerArray) to High(IntegerArray) do
|
|
for Idx := Low(IntegerArray) to High(IntegerArray) do
|
|
IntegerArray[Idx] := JSONArray.Integers[Idx];
|
|
IntegerArray[Idx] := JSONArray.Integers[Idx];
|
|
|
|
+ SetDynArrayProp(Self,P,Pointer(IntegerArray));
|
|
end;
|
|
end;
|
|
|
|
|
|
- procedure SetUnicodeStringArrayProp(PropAsPtr: Pointer;
|
|
|
|
- const JSONArray: TJSONArray);
|
|
|
|
|
|
+ procedure SetUnicodeStringArrayProp(const JSONArray: TJSONArray);
|
|
var
|
|
var
|
|
- UnicodeStringArray: TUnicodeStringArray;
|
|
|
|
|
|
+ UnicodeStringArray: TUnicodeStringArray = nil;
|
|
Idx: Integer;
|
|
Idx: Integer;
|
|
begin
|
|
begin
|
|
- UnicodeStringArray := TUnicodeStringArray(PropAsPtr);
|
|
|
|
SetLength(UnicodeStringArray, JSONArray.Count);
|
|
SetLength(UnicodeStringArray, JSONArray.Count);
|
|
for Idx := Low(UnicodeStringArray) to High(UnicodeStringArray) do
|
|
for Idx := Low(UnicodeStringArray) to High(UnicodeStringArray) do
|
|
UnicodeStringArray[Idx] := UTF8Decode(JSONArray.Strings[Idx]);
|
|
UnicodeStringArray[Idx] := UTF8Decode(JSONArray.Strings[Idx]);
|
|
|
|
+ SetDynArrayProp(Self,P,Pointer(UnicodeStringArray));
|
|
end;
|
|
end;
|
|
|
|
|
|
- procedure SetStringArrayProp(PropAsPtr: Pointer;
|
|
|
|
- const JSONArray: TJSONArray);
|
|
|
|
|
|
+ procedure SetStringArrayProp(const JSONArray: TJSONArray);
|
|
var
|
|
var
|
|
|
|
+ StringArray: TStringArray = nil;
|
|
Idx: Integer;
|
|
Idx: Integer;
|
|
- StringArray: TStringArray;
|
|
|
|
begin
|
|
begin
|
|
- StringArray := TStringArray(PropAsPtr);
|
|
|
|
SetLength(StringArray, JSONArray.Count);
|
|
SetLength(StringArray, JSONArray.Count);
|
|
for Idx := Low(StringArray) to High(StringArray) do
|
|
for Idx := Low(StringArray) to High(StringArray) do
|
|
StringArray[Idx] := JSONArray.Strings[Idx];
|
|
StringArray[Idx] := JSONArray.Strings[Idx];
|
|
|
|
+
|
|
|
|
+ //SetDynArrayProp handles:
|
|
|
|
+ // 1)If the property holds an existing array, free it if the ref count is 0
|
|
|
|
+ // 2)Increments the ref count of our new array when it sets the property
|
|
|
|
+ SetDynArrayProp(Self,P,Pointer(StringArray));
|
|
end;
|
|
end;
|
|
|
|
|
|
Var
|
|
Var
|
|
- T : PTypeData;
|
|
|
|
- L : TBaseObjectList;
|
|
|
|
- D : TJSONEnum;
|
|
|
|
- PTD : PTypeData;
|
|
|
|
|
|
+ PTD: PTypeData;
|
|
|
|
+ L : TBaseObjectList;
|
|
|
|
+ D : TJSONEnum;
|
|
ET : PTypeInfo;
|
|
ET : PTypeInfo;
|
|
AN : String;
|
|
AN : String;
|
|
- AP : Pointer;
|
|
|
|
- S : TJSONSchema;
|
|
|
|
|
|
+ S : TJSONSchema;
|
|
|
|
|
|
begin
|
|
begin
|
|
|
|
+ Assert((P<>nil) and Assigned(AValue), 'TBaseObject.SetArrayProperty: P or AValue is nil');
|
|
|
|
+
|
|
if P^.PropType^.Kind=tkClass then
|
|
if P^.PropType^.Kind=tkClass then
|
|
begin
|
|
begin
|
|
- T:=GetTypeData(P^.PropType);
|
|
|
|
- if T^.ClassType.InheritsFrom(TBaseObjectList) then
|
|
|
|
|
|
+ PTD:=GetTypeData(P^.PropType);
|
|
|
|
+ if PTD^.ClassType.InheritsFrom(TBaseObjectList) then
|
|
begin
|
|
begin
|
|
- L:=TBaseObjectList(TBaseObjectClass(T^.ClassType).Create);
|
|
|
|
- { #todo -oWayneSherman : what if there is an existing object, are we clobbering it? }
|
|
|
|
|
|
+ L:=TBaseObjectList(TBaseObjectClass(PTD^.ClassType).Create);
|
|
|
|
+ GetObjectProp(Self,P).Free; //if the property holds an object, free it
|
|
SetObjectProp(Self,P,L);
|
|
SetObjectProp(Self,P,L);
|
|
For D in AValue do
|
|
For D in AValue do
|
|
L.AddObject('').LoadFromJSON(D.Value as TJSONObject);
|
|
L.AddObject('').LoadFromJSON(D.Value as TJSONObject);
|
|
end
|
|
end
|
|
- else if T^.ClassType.InheritsFrom(TJSONSchema) then
|
|
|
|
|
|
+ else if PTD^.ClassType.InheritsFrom(TJSONSchema) then
|
|
begin
|
|
begin
|
|
S:=TJSONSchema.Create;
|
|
S:=TJSONSchema.Create;
|
|
S.SetArrayProperty(P,AValue);
|
|
S.SetArrayProperty(P,AValue);
|
|
- { #todo -oWayneSherman : what if there is an existing object, are we clobbering it? }
|
|
|
|
|
|
+ GetObjectProp(Self,P).Free; //if the property holds an object, free it
|
|
SetObjectProp(Self,P,S);
|
|
SetObjectProp(Self,P,S);
|
|
end
|
|
end
|
|
else
|
|
else
|
|
- Raise ERESTAPI.CreateFmt('Unsupported class %s for property %s',[T^.ClassType.ClassName,P^.Name]);
|
|
|
|
|
|
+ Raise ERESTAPI.CreateFmt('Unsupported class %s for property %s',[PTD^.ClassType.ClassName,P^.Name]);
|
|
end
|
|
end
|
|
else if P^.PropType^.Kind=tkDynArray then
|
|
else if P^.PropType^.Kind=tkDynArray then
|
|
begin
|
|
begin
|
|
- // Get array value
|
|
|
|
- AP:=GetObjectProp(Self,P); //NOTE: AP is dynanmic array as an untyped pointer
|
|
|
|
- //Getting it like this bypasses the reference count management
|
|
|
|
- //Be careful what do we with it to avoid leaking memory.
|
|
|
|
PTD:=GetTypeData(P^.PropType);
|
|
PTD:=GetTypeData(P^.PropType);
|
|
ET:=PTD^.ElType2;
|
|
ET:=PTD^.ElType2;
|
|
AN:=ET^.Name;
|
|
AN:=ET^.Name;
|
|
case ET^.Kind of
|
|
case ET^.Kind of
|
|
- tkClass: SetObjectArrayProp(AP, ET^.Name, GetTypeData(ET)^.ClassType, AValue);
|
|
|
|
|
|
+ tkClass: SetObjectArrayProp(ET^.Name, GetTypeData(ET)^.ClassType, AValue);
|
|
tkFloat:
|
|
tkFloat:
|
|
if IsDateTimeProp(ET) then
|
|
if IsDateTimeProp(ET) then
|
|
- SetDateTimeArrayProp(AP, AValue)
|
|
|
|
|
|
+ SetDateTimeArrayProp(AValue)
|
|
else
|
|
else
|
|
- SetFloatArrayProp(AP, AValue);
|
|
|
|
|
|
+ SetFloatArrayProp(AValue);
|
|
|
|
|
|
- tkInt64: SetInt64ArrayProp(AP, AValue);
|
|
|
|
- tkBool: SetBooleanArrayProp(AP, AValue);
|
|
|
|
- tkInteger: SetIntegerArrayProp(AP, AValue);
|
|
|
|
|
|
+ tkInt64: SetInt64ArrayProp(AValue);
|
|
|
|
+ tkBool: SetBooleanArrayProp(AValue);
|
|
|
|
+ tkInteger: SetIntegerArrayProp(AValue);
|
|
tkUstring,
|
|
tkUstring,
|
|
- tkWstring: SetUnicodeStringArrayProp(AP, AValue);
|
|
|
|
|
|
+ tkWstring: SetUnicodeStringArrayProp(AValue);
|
|
tkString,
|
|
tkString,
|
|
tkAstring,
|
|
tkAstring,
|
|
- tkLString: SetStringArrayProp(AP, AValue);
|
|
|
|
|
|
+ tkLString: SetStringArrayProp(AValue);
|
|
else
|
|
else
|
|
Raise ERESTAPI.CreateFmt('%s: unsupported array element type for property of type %s: %s',[ClassName,AN,GetEnumName(TypeInfo(TTypeKind),Ord(ET^.Kind))]);
|
|
Raise ERESTAPI.CreateFmt('%s: unsupported array element type for property of type %s: %s',[ClassName,AN,GetEnumName(TypeInfo(TTypeKind),Ord(ET^.Kind))]);
|
|
end;
|
|
end;
|
|
@@ -843,8 +844,8 @@ end;
|
|
|
|
|
|
procedure TBaseObject.SetObjectProperty(P: PPropInfo; AValue: TJSONObject);
|
|
procedure TBaseObject.SetObjectProperty(P: PPropInfo; AValue: TJSONObject);
|
|
Var
|
|
Var
|
|
|
|
+ ObjectArray : TObjectArray;
|
|
O : TBaseObject;
|
|
O : TBaseObject;
|
|
- A: Pointer;
|
|
|
|
T : PTypeData;
|
|
T : PTypeData;
|
|
D : TJSONEnum;
|
|
D : TJSONEnum;
|
|
AN : String;
|
|
AN : String;
|
|
@@ -855,17 +856,17 @@ Var
|
|
begin
|
|
begin
|
|
if P^.PropType^.Kind=tkDynArray then
|
|
if P^.PropType^.Kind=tkDynArray then
|
|
begin
|
|
begin
|
|
- A:=GetDynArrayProp(P);
|
|
|
|
- For I:=0 to Length(TObjectArray(A))-1 do
|
|
|
|
- FreeAndNil(TObjectArray(A)[i]);
|
|
|
|
- SetLength(TObjectArray(A),AValue.Count);
|
|
|
|
|
|
+ ObjectArray:=TObjectArray(GetDynArrayProp(Self,P));
|
|
|
|
+ For I:=Low(ObjectArray) to High(ObjectArray) do
|
|
|
|
+ FreeAndNil(ObjectArray[i]);
|
|
|
|
+ SetLength(ObjectArray,AValue.Count);
|
|
T:=GetTypeData(P^.PropType);
|
|
T:=GetTypeData(P^.PropType);
|
|
AN:=T^.ElType2^.Name;
|
|
AN:=T^.ElType2^.Name;
|
|
I:=0;
|
|
I:=0;
|
|
For D in AValue do
|
|
For D in AValue do
|
|
begin
|
|
begin
|
|
O:=CreateObject(AN);
|
|
O:=CreateObject(AN);
|
|
- TObjectArray(A)[I]:=O;
|
|
|
|
|
|
+ (ObjectArray)[I]:=O;
|
|
// Writeln(ClassName,' Adding instance of type: ',AN,' for key ',D.Key);
|
|
// Writeln(ClassName,' Adding instance of type: ',AN,' for key ',D.Key);
|
|
if IsPublishedProp(O,'name') then
|
|
if IsPublishedProp(O,'name') then
|
|
SetStrProp(O,'name',D.Key);
|
|
SetStrProp(O,'name',D.Key);
|
|
@@ -873,7 +874,7 @@ begin
|
|
Inc(I);
|
|
Inc(I);
|
|
end;
|
|
end;
|
|
// Writeln(ClassName,' Done with array ',P^.Name,', final array length: ', Length(TObjectArray(A)));
|
|
// Writeln(ClassName,' Done with array ',P^.Name,', final array length: ', Length(TObjectArray(A)));
|
|
- SetDynArrayProp(P,A);
|
|
|
|
|
|
+ SetDynArrayProp(Self,P,Pointer(ObjectArray));
|
|
Exit;
|
|
Exit;
|
|
end;
|
|
end;
|
|
if Not (P^.PropType^.Kind=tkClass) then
|
|
if Not (P^.PropType^.Kind=tkClass) then
|
|
@@ -1021,7 +1022,7 @@ begin
|
|
A:=TJSONArray.Create;
|
|
A:=TJSONArray.Create;
|
|
Result:=A;
|
|
Result:=A;
|
|
// Get array value type
|
|
// Get array value type
|
|
- AP:=GetObjectProp(Self,P);
|
|
|
|
|
|
+ AP:=GetDynArrayProp(Self,P);
|
|
PTD:=GetTypeData(P^.PropType);
|
|
PTD:=GetTypeData(P^.PropType);
|
|
ET:=PTD^.ElType2;
|
|
ET:=PTD^.ElType2;
|
|
// Fill in all elements
|
|
// Fill in all elements
|
|
@@ -1082,18 +1083,10 @@ begin
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TBaseObject.ClearChildren(ChildTypes: TChildTypes);
|
|
procedure TBaseObject.ClearChildren(ChildTypes: TChildTypes);
|
|
-
|
|
|
|
-
|
|
|
|
-Type
|
|
|
|
- TObjectArr = Array of TObject;
|
|
|
|
-
|
|
|
|
var
|
|
var
|
|
PL: PPropList;
|
|
PL: PPropList;
|
|
P : PPropInfo;
|
|
P : PPropInfo;
|
|
- i,j,count,len:integer;
|
|
|
|
- A : pointer;
|
|
|
|
- PTD : PTypeData;
|
|
|
|
- O : TObject;
|
|
|
|
|
|
+ i,count:integer;
|
|
|
|
|
|
begin
|
|
begin
|
|
Count:=GetPropList(Self,PL);
|
|
Count:=GetPropList(Self,PL);
|
|
@@ -1104,31 +1097,13 @@ begin
|
|
case P^.PropType^.Kind of
|
|
case P^.PropType^.Kind of
|
|
tkClass:
|
|
tkClass:
|
|
if (ctObject in ChildTypes) then
|
|
if (ctObject in ChildTypes) then
|
|
- begin
|
|
|
|
- // Writeln(ClassName,' Examining object: ',P^.Name);
|
|
|
|
- O:=GetObjectProp(Self,P);
|
|
|
|
- O.Free;
|
|
|
|
- SetObjectProp(Self,P,Nil);
|
|
|
|
- end;
|
|
|
|
|
|
+ Self.ClearProperty(P);
|
|
tkDynArray:
|
|
tkDynArray:
|
|
if (ctArray in ChildTypes) then
|
|
if (ctArray in ChildTypes) then
|
|
- begin
|
|
|
|
- len:=Length(P^.PropType^.Name);
|
|
|
|
- PTD:=GetTypeData(P^.PropType);
|
|
|
|
- if PTD^.ElType2^.Kind=tkClass then
|
|
|
|
- begin
|
|
|
|
- A:=GetDynArrayProp(P);
|
|
|
|
-{$IFDEF DUMPARRAY}
|
|
|
|
- DumpArray(ClassName+' (clear)',P^.PropType^.Name,A);
|
|
|
|
-{$ENDIF}
|
|
|
|
-// Writeln(ClassName,' Examining array: ',P^.Name,'Count:',Length(TObjectArr(A)));
|
|
|
|
- For J:=0 to Length(TObjectArr(A))-1 do
|
|
|
|
- begin
|
|
|
|
- FreeAndNil(TObjectArr(A)[J]);
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
- // Length is set to nil by destructor
|
|
|
|
- end;
|
|
|
|
|
|
+ Self.ClearProperty(P);
|
|
|
|
+ else
|
|
|
|
+ //do nothing
|
|
|
|
+ //only properties with objects or dyn arrays have children
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
finally
|
|
@@ -1323,6 +1298,8 @@ begin
|
|
else
|
|
else
|
|
SetArrayProperty(P,TJSONArray(json));
|
|
SetArrayProperty(P,TJSONArray(json));
|
|
jtObject : SetObjectProperty(P,TJSONObject(json));
|
|
jtObject : SetObjectProperty(P,TJSONObject(json));
|
|
|
|
+ else
|
|
|
|
+ //do nothing
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1348,6 +1325,8 @@ begin
|
|
tkQWord : Result:=GetQWordProperty(Info);
|
|
tkQWord : Result:=GetQWordProperty(Info);
|
|
tkInt64 : Result:=GetInt64Property(Info);
|
|
tkInt64 : Result:=GetInt64Property(Info);
|
|
tkInteger : Result:=GetIntegerProperty(Info);
|
|
tkInteger : Result:=GetIntegerProperty(Info);
|
|
|
|
+ else
|
|
|
|
+ //do nothing
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|