Written by

Manager, Application Services at InterSystems
Question Ben Spead · Apr 12, 2023

Code to copy class definition from one Namespace to another?

I have a situation where I have a handful of classes which I need to copy to another Namespace (which uses a different RoutineDB) on the same instance, load it and compile it.

Can anyone help me come up with a command that will do this quickly and easily?   Perhaps something with extended reference?  

This is somewhat time sensitive so thank you in advance for your ideas!

Comments

Otto Medin  Apr 12, 2023 to Matthew Giesmann

Yes, with a ZNSPACE in between.

0
Ben Spead  Apr 12, 2023 to Matthew Giesmann

Thanks Matt, I am trying to avoid using the OS as the middle-man in this case as we have 300+ namespaces to do this on and so should be scripted.  I can create a %Method that would do this but was hoping for a quick command that could just do the transfer

0
Vic Sun  Apr 12, 2023 to Ben Spead

You could use %Dictionary.ClassDefinition to open the class definitions, use %ConstructClone and then save to another namespace.

0
Ben Spead  Apr 12, 2023 to Vic Sun

Thanks Vik ... that sounds like a good approach to play with!

0
Chad Severtson · Apr 12, 2023

Consider $System.OBJ.ExportToStream() and .LoadStream() to avoid local files with a change to the appropriate implicit namespace between. 

0
Ben Spead  Apr 12, 2023 to Chad Severtson

Thanks Chad - I think that this would be the lowest impact overhead approach if I don't copy the definitions directly via a clone or the globals

0
Timothy Leavitt · Apr 12, 2023
Set source = "NAMESPACE1"
Set target = "NAMESPACE2"
Kill ^|target|oddDEF(classname)
Merge ^|target|oddDEF(classname) = ^|source|oddDEF(classname)
New $Namespace
Set $Namespace = target
$$$ThrowOnError($System.OBJ.Compile(classname,"ck"))

EDIT: Don't do this. Everybody should ignore me and do what @Chad Severtson said instead.

0
Ben Spead  Apr 12, 2023 to Timothy Leavitt

thanks Tim - this is along the lines of what I was thinking about.  Much appreciated!

0
David Van De Griek  Apr 12, 2023 to Timothy Leavitt

You also need to merge over the index entry in ^rINDEXCLASS($$$UPPER(classname)) to the new namespace.

Don't forget to move all related classes such as Serial classes, datatype classes, super classes, references, etc.

0
Timothy Leavitt  Apr 13, 2023 to David Van De Griek

This is exactly why my quick-and-dirty approach didn't (seem to?) work in a first quick attempt. ExportToStream/LoadStream it is!

(for context, this is moving class definitions over in conjunction with changing routine mappings)

0
Benjamin De Boe  Apr 13, 2023 to Timothy Leavitt

Please do NOT make any assumptions about system globals such as the ^odd series. User code should stick to documented APIs such as the Export and Clone options described earlier in the thread.

0
Scott Roth · Apr 12, 2023

Could you create an %ALL namespace and map the the routines in the %ALL namespace so they are available across all the namespaces?

0
Ben Spead  Apr 12, 2023 to Scott Roth

We are using %ALL for some other things but unfortunately it won't apply in this case.  Specifically, this is for a HS instance where we need to move auto-created classes into a new routine DB.  So I can't add a mapping for each and every package (300 packages).

0
Ben Spead  Apr 12, 2023 to Clark Matthews

Thanks Clark - this is one of the approaches I hadn't thought of previously 

0
Robert Cemper · Apr 12, 2023

with studio, I open 1 for each namespace and then drag and drop it from 1 NS to the other
works single or multiple
not so useful for 300.  ns %ALL looks more promising

0
Ben Spead  Apr 12, 2023 to Robert Cemper

thanks for the input Robert ... %All is powerful but won't work for me in this scenario. 

0
Ben Spead  Apr 12, 2023 to Eduard Lebedyuk

300 unique packages makes this approach unwieldy 

0
Enrico Parisi · May 16, 2023

I know this is old, but recently I found a new way to export/import a package to a global, this may simplify the solution.

1) create a studio project with all the classes that need to me exported. This can be done programmatically, create an instance of %Studio.Project, use AddItem()...etc.

2) Export the project to a global like ^IRIS.Temp("myProjExport"). Open %Studio.Project, export ot global using DeployToGbl() method

3) in target namespace import calling ##class(%Studio.Project).InstallFromGbl()

Using ^IRIS.Temp has the advantage of easy/shared access from all namespaces.

Enrico

0