Dissecting an OREF
When an object is created in memory, the object reference (OREF) is represented as a string value when displayed with the Write command:
HICG>Set pat=##class(JD.Sample.patient).%OpenId(70)
HICG>Write pat
1@JD.Sample.patient ; "stringified" OREF
HICG>Zwrite pat
pat=1@JD.Sample.patient ; <OREF>
+----------------- general information ---------------
| oref value: 1
| class name: JD.Sample.patient
| %%OID: $lb("70","JD.Sample.patient")
| reference count: 2
+----------------- attribute values ------------------
| %Concurrency = 1 <Set>
| address = "4 Foo St"
| city = "Springfield"
| dob = "2001-02-19"
| email = "johndoe.fakeemail.fake"
| firstname = "John"
| lastname = "Doe"
| mobile = "617-555-1212"
| mrn = 124124
| name = "John Doe"
| phone = "617-555-0501"
| state = "MA"
| zip = "01234-5678"
+-----------------------------------------------------
Given the string "1@JD.Sample.patient," is there a way to convert that back to an OREF? I realize there is a variable that is specifically assigned as this object, but is there any way to manipulate the string representation to access the object's properties/methods?
This isn't a problem that necessarily needs a solution. I'm just wondering what the individual elements of the string represent; the last is obviously the classname, but what does the n@ indicate/describe, and can it be used along with the classname to assemble an OREF to the object?
Comments
@ is just a separator
while n is just an internal sequence number within your partition
see this example
SAMPLES>s a=##class(Sample.Person).%OpenId(2)
SAMPLES>s b=##class(Sample.Person).%OpenId(12)
SAMPLES>s c=##class(Sample.Employee).%OpenId(111)
SAMPLES>s d=##class(Sample.Company).%OpenId(9)
SAMPLES>zw
a=<OBJECT REFERENCE>[1@Sample.Person]
b=<OBJECT REFERENCE>[2@Sample.Person]
c=<OBJECT REFERENCE>[3@Sample.Employee]
d=<OBJECT REFERENCE>[4@Sample.Company]
SAMPLES>Thanks! I figured it was something like that. But is there method/function that will create a reference to the instantiated object from the sequence number and classname?
you just can copy an already existing reference SET rerf=a from the example above
to show all open objects:Do $System.OBJ.ShowObjects()
Oref Class Name Ref Count
---- ---------- ---------
1 Sample.Person 1
2 Sample.Person 1
3 Sample.Employee 1
4 Sample.Company 1
OR
Do $System.OBJ.ShowObjects("/detail=1")
Oref Class Name Ref Count
---- ---------- ---------
1 Sample.Person 1
+----------------- general information ---------------
| oref value: 1
| class name: Sample.Person
| %%OID: $lb("2","Sample.Person")
| reference count: 1
+----------------- attribute values ------------------
| %Concurrency = 1 <Set>
| DOB = 32225
| Name = "Ubertini,Brian S."
| SSN = "231-12-5250"
+----------------- swizzled references ---------------
| i%FavoriteColors = "" <Set>
| r%FavoriteColors = "" <Set>
| i%Home = $lb("9177 First Court","Bensonhurst","SC",42658) <Set>
| r%Home = "" <Set>
| i%Office = $lb("260 First Place","Larchmont","NV",99593) <Set>
| r%Office = "" <Set>
| i%Spouse = ""
| r%Spouse = ""
+--------------- calculated references ---------------
| Age <Get>
+-----------------------------------------------------
2 Sample.Person 1
+----------------- general information ---------------
| oref value: 2
| class name: Sample.Person
| %%OID: $lb("12","Sample.Person")
| reference count: 1
+----------------- attribute values ------------------
| %Concurrency = 1 <Set>
| DOB = 33423
| Name = "Waal,Jeff V."
| SSN = "137-61-1656"
+----------------- swizzled references ---------------
| i%FavoriteColors = "" <Set>
| r%FavoriteColors = "" <Set>
| i%Home = $lb("3872 Washington Place","Newton","NJ",80886) <Set>
| r%Home = "" <Set>
| i%Office = $lb("4339 Second Drive","Albany","PA",79202) <Set>
| r%Office = "" <Set>
| i%Spouse = ""
| r%Spouse = ""
+--------------- calculated references ---------------
| Age <Get>
+-----------------------------------------------------
3 Sample.Employee 1
+----------------- general information ---------------
| oref value: 3
| class name: Sample.Employee
| %%OID: $lb("111","Sample.Employee")
| reference count: 1
+----------------- attribute values ------------------
| %Concurrency = 1 <Set>
| DOB = 50109
| Name = "Yezek,Chelsea F."
| SSN = "227-72-8394"
| Salary = 69426
| Title = "Executive WebMaster"
+----------------- swizzled references ---------------
| i%Company = 2 <Set>
| r%Company = "" <Set>
| i%FavoriteColors = ""
|i%FavoriteColors(1) = "Blue"
|i%FavoriteColors(2) = "Yellow"
| r%FavoriteColors = "" <Set>
| i%Home = $lb("7573 Main Drive","Bensonhurst","MA",97453) <Set>
| r%Home = "" <Set>
| i%Notes = "" <Set>
| r%Notes = "" <Set>
| i%Office = $lb("7403 Oak Place","Vail","NH",46047) <Set>
| r%Office = "" <Set>
| i%Picture = "" <Set>
| r%Picture = "" <Set>
| i%Spouse = 89
| r%Spouse = ""
+--------------- calculated references ---------------
| Age <Get>
+-----------------------------------------------------
4 Sample.Company 1
+----------------- general information ---------------
| oref value: 4
| class name: Sample.Company
| %%OID: $lb("9","Sample.Company")
| reference count: 1
+----------------- attribute values ------------------
| %Concurrency = 1 <Set>
| Mission = "Leaders in dynamic nano-application development instruments for the desktop."
| Name = "BioDyne LLC."
| Revenue = 928565856
| TaxID = "X6668"
+----------------- swizzled references ---------------
| i%Employees = $lb("Sample.Employee","Company",4,"many",1,1) <Set>
| r%Employees = "" <Set>
+-----------------------------------------------------
Then you can use %%OID to generate your own OREF
like set ref=##class(%Persistent).%Open($lb("9","Sample.Company"))
It's not really comfortable
But is there method/function that will create a reference to the instantiated object from the sequence number and classname?
So ... no? ![]()
I'll think it over. I have some dirty ideas. need to check it
it's kind of useful golf for me.
it is possible. but an OREF is always a LOCAL reference !
see this example
SAM>kill
SAM>set a=##class(Sample.Person).%OpenId(2)
SAM>set b=##class(Sample.Person).%OpenId(12)
SAM>set c=##class(Sample.Person).%OpenId(111)
SAM>set x="3@Sample.Person" ;what we look for
SAM>set o="" ;this will be our OREF
SAM>zw
a=<OBJECT REFERENCE>[4@Sample.Person]
b=<OBJECT REFERENCE>[3@Sample.Person]
c=<OBJECT REFERENCE>[2@Sample.Employee]
o=""
x="3@Sample.Person"
SAM>;; now we convert our String x to OREF o
SAM>for set o=$zobjnext(o) quit:(o="")||($p(o,"?")=x)
SAM>zw ;; we did it
a=<OBJECT REFERENCE>[4@Sample.Person]
b=<OBJECT REFERENCE>[3@Sample.Person]
c=<OBJECT REFERENCE>[2@Sample.Employee]
o=<OBJECT REFERENCE>[3@Sample.Person]
x="3@Sample.Person"
SAM>
The key-oneliner:for set o=$zobjnext(o) quit:(o="")||($p(o,"?")=x)
there was some GOLF work to do
set o="" for set o=$zobjnext(o) quit:(o="")||($p(o,"?")=x)
MUCH more simple and shorter
kill
set a=##class(Sample.Person).%OpenId(2)
set b=##class(Sample.Person).%OpenId(12)
set c=##class(Sample.Person).%OpenId(111)
set obj=$zobjref("2@Sample.Person")
;; BINGO
zw
a=<OBJECT REFERENCE>[1@Sample.Person]
b=<OBJECT REFERENCE>[2@Sample.Person]
c=<OBJECT REFERENCE>[3@Sample.Employee]
obj=<OBJECT REFERENCE>[2@Sample.Person]Hah! As always, you're THE MAN! ![]()
Now, why isn't $ZOBJREF() in the documentation? I sure would have noticed that ...
Now, why isn't $ZOBJREF() in the documentation?
What's the use case for this function?
Here's some (autotranslated) info about thesefunctions.
Also $zobjref accepts only integers, so you can pass just the part before @:
set a={}
set b={}
set obj1=$zobjref(1)
set obj2=$zobjref("1@Sample.Person")
zwResults in:
a=<OBJECT REFERENCE>[1@%Library.DynamicObject]
b=<OBJECT REFERENCE>[2@%Library.DynamicObject]
obj1=<OBJECT REFERENCE>[1@%Library.DynamicObject]
obj2=<OBJECT REFERENCE>[1@%Library.DynamicObject]There's also no guarantee that the object would be the same i.e.:
set a={"a":1}
set b={"b":1}
set aoref = ""_ a
kill a
set c={"c":1}
set obja=$zobjref(aoref)
zw obja
> obja={"c":1} ; <DYNAMIC OBJECT>right! Just the stating numeric is important
i will elaborate on the background of objects
What's the use case for this function?
ISC's Interoperability business rule editor has some quirks; it does not allow the passing of variables by reference to custom methods and that will cause objects to be passed as the OREF string in some cases. I was wondering if there was a way to work around that by obtaining another reference to the object by its OREF string, since that's what i ended up with.
I haven't tried this yet ... it may not work for the specific scenario I encountered. But this discussion has certainly helped me understand how things work under the covers a bit better.
ISC's Interoperability business rule editor has some quirks; it does not allow the passing of variables by reference to custom methods
Interesting. Can you post sample code please?
It is dating back to the very early days of Caché. Even before my time @ ISC
(my guess >25 years) There was a lot of $Z* stuff e.g. $ZU(..)
That was not meant to be used for applications.
Just for internal use in system utilities. With no public Docs.
Some became public over time, mostly renamed, and were documented.
I just found it by examing some related system functions.