KNOWLEDGE BASE
Log In    |    Knowledge Base    |    4D Home
Tech Tip: Two Methods to copy object/collection to shared object/collection
PRODUCT: 4D | VERSION: 17 | PLATFORM: Mac & Win
Published On: February 8, 2019
Your current browser may not allow you to download the asset. We recommend Mozilla Firefox or Google Chrome.
Log In

Storage method in V17 enables sharing objects and collections across all processes including preemptive ones. 4D Storage only accept shared objects or collections as its properties. Each modification of Storage and its properties needs to be surrounded by Use...End use.
When we want to share an existing object to other processes using Storage, the best strategy is to create a shared object in Storage and copy the value to the shared object. However, a shared object does not support OB COPY or copying using “:=” assignment. The following code:

C_OBJECT($person)
$person:=New object
$person.firstName:="Jon"
$person.lastName:="Doe"
$person.age:=20
$person.profile:=New object("health";"good")
$person.familyMembers:=New collection(new object("firstName";"Jane";"lastName";"Doe";"relationship";"mother";"age";"50"))
Use (Storage)
   Storage.person:=New shared object
   Use (Storage.person)
   Storage.person:=$person
  //Storage.person:=OB COPY($person) will fail as well
   End use
End use


Will generate an “unsupported value type” error:



This is because shared object can only be modified in two ways: via New shared object method at initialization, or via object notation to add one property at a time. Copying from other object will change the structure of shared object and cause failure.

Below is a method that extracts all properties of an object into an array, then assign each property to the shared object:

//Method: OB_CopyToSharedObject
//$1: Object to copy from
//$2: Shared Object to copy to

C_OBJECT($1;$2)
ARRAY TEXT($arrNames;0)
OB GET PROPERTY NAMES($1;$arrNames;$arrTypes)
For ($counter;1;Size of array($arrNames))
   Case of
   //Attribute type is object, copy with OB_CopyObject again
   : ($arrTypes{$counter}=Is object)
     $2[$arrNames{$counter}]:=New shared object
     Use ($2[$arrNames{$counter}])
       OB_CopyToSharedObject ($1[$arrNames{$counter}];$2[$arrNames{$counter}])
     End use
     //Attribute type is collection, copy with OB_CopyCollection
   : ($arrTypes{$counter}=Is collection)
     $2[$arrNames{$counter}]:=New shared collection
     Use ($2[$arrNames{$counter}])
       OB_CopyToSharedCollection ($1[$arrNames{$counter}];$2[$arrNames{$counter}])
     End use
   Else
   // The rest supported types can be copied directly.
     $2[$arrNames{$counter}]:=$1[$arrNames{$counter}]
   End case
End for


A property of an object could be one of three types: object, collection, and storage. Object and collection typed properties need to be converted to shared object/collection before they can be copied. In the code below, OB_CopyToSharedObject is called to copy object property, and a new method OB_CopyToSharedCollection is called to copy collection property:

//Method:OB_CopyToSharedCollection
//$1:Collection to copy from
//$2:Shared Collection to copy to

C_COLLECTION($1;$2)
C_LONGINT($counter)

For ($counter;0;$1.length-1)
   Case of
   : (Value type($1[$counter])=Is object)
     $2[$counter]:=New shared object
     Use ($2[$counter])
       //Element type is object, copy with OB_CopyObject
       OB_CopyToSharedObject ($1[$counter];$2[$counter])
     End use
   : (Value type($1[$counter])=Is collection)
   //Element type is collection, copy with OB_CopyCollection //Element type is collection, copy with OB_CopyCollection//Element type is collection, copy with OB_CopyCollection
     $2[$counter]:=New shared collection
     Use ($2[$counter])
       OB_CopyToSharedCollection ($1[$counter];$2[$counter])
     End use
   Else
      // Other supported types can be copied directly.
     $2[$counter]:=$1[$counter]
   End case
End for


To copy the object defined at the top into an shared object, using OB_CopyToSharedObject instead of OB COPY:

Use (Storage)
   Storage.person:=New shared object
   Use (Storage.person)
   OB_CopyToSharedObject ($person;Storage.person)
   End use
End use

can copy the object into Storage.person successfully.

This Tech Tip was originally written with one method to copy shared object only. Mr. Keith White poinited out that it needs to include a mehtod for shared collections when object propertie is a collection. He provided a two-method solution which works with both shared object and collection with object/collection typed properties/elements.

His post can be found at: http://forums.4d.com/Post/EN/28324700/1/28326815#28326815

Commented by Xiang Liu on January 30, 2019 at 8:35 AM
Hi Keith, Thanks for testing the code and pointing out my oversight. I have updated the code of CopyAllObjProperties method. It can copy object properties that are collections to a shared object. Let me know if you have any other question Thanks!
Commented by Keith White on January 30, 2019 at 5:19 AM
The article says: "This method works for assigning any object to an existing shared object, it supports all property types including object and collection." It doesn't seem to work for object properties that are collections?