Article
· Oct 4, 2016 6m read

How to add a parameter to a class programmatically

This sample class will add parameter DSINTERVAL to each class containing the parameter DSTIME

To execute it from a Terminal :


SAMPLES>d ##class(adm.param).add(,,1)
[SAMPLES] parameter DSINTERVAL=5 added to class DeepSee.Study.CityRainfall (via adm.param)
[SAMPLES] parameter DSINTERVAL=5 added to class HoleFoods.Transaction (via adm.param)
[SAMPLES] parameter DSINTERVAL=5 added to class News.DeepSee.NewsArticle (via adm.param)
DSINTERVAL parameter was added to 3 classes

Class adm.param [ Abstract ]
{

/// this class will add DSINTERVAL parameter to each class containing DSTIME
/// in order to synchronize a cube that is based on a source table on a mirror system
/// see: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=D2IMP_ch_current#D2IMP_current_dstime_enabling
ClassMethod add(name As %String = "DSINTERVAL", value As %String = "5", verbose As %Boolean = 0) As %Status
{
    set sc = $$$OK
    try {
        set statement = ##class(%SQL.Statement).%New()
        // %Dictionary classes are useful to select classes based on their content
        // here we use %Dictionary.ParameterDefinition class which contains all the parameters defined in all classes
        // then we will open the parent class to add the missing parameter
        set query="SELECT a.parent "
                 _"FROM %Dictionary.ParameterDefinition a "
                 _"WHERE a.name='DSTIME' "
                 _"AND substr(a.parent,1,1)<>'%' "
                 _"AND NOT EXISTS (SELECT null "
                 _"FROM %Dictionary.ParameterDefinition b "
                 _"WHERE b.name='"_name_"' and b.parent=a.parent)"
        set sc = statement.%Prepare(query)
        quit:$$$ISERR(sc)
        set classes="",nb=0
        set rs = statement.%Execute()
        while (rs.%Next(.sc)) {
            quit:$$$ISERR(sc)
            if (rs.parent '="") {
                // opening of the parent class 
                set class = ##class(%Dictionary.ClassDefinition).%OpenId(rs.parent)
                if $IsObject(class) {
                    // creating the new parameter
                    set param=##class(%Dictionary.ParameterDefinition).%New()
                    set param.Name=name
                    set param.Default=value
                    // adding the parameter to the parent class
                    do class.Parameters.Insert(param)
                    set sc=class.%Save()
                    // if parent class is successfully saved set the following message
                    set:sc msg="["_$namespace_"] parameter "_name_"="_value_" added to class "_rs.parent_" (via "_..%ClassName(1)_")",severity=0
                    // if parent class is not saved set the following message
                    set:'sc msg="["_$namespace_"] ERROR while saving "_rs.parent_" after having added the parameter "_name_"="_value_" (via "_..%ClassName(1)_") :"_$system.Status.GetErrorText(sc),severity=1
                    // if verbose=1 write the message to the terminal
                    write:verbose msg,!
                    // write the message to cconsole.log
                    do ##class(%SYS.System).WriteToConsoleLog(msg,verbose,severity)
                    // add the class name to compile 
                    set classes(rs.parent)="",nb=$increment(nb)
                }
            }
        }
        set:nb=0 msg=name_" parameter was not added to any class"
        set:nb=1 msg=name_" parameter was added to "_nb_" class"
        set:nb>1 msg=name_" parameter was added to "_nb_" classes"
        write:verbose msg,!
        // compile all modified classes 
        if nb>0 { 
            set sc=$system.OBJ.Compile(.classes,"ck"_$select(verbose:"d",1:"-d"))
            set:sc msg="["_$namespace_"] modified "_$select(nb=1:"class",1:"classes")_" successfully compiled",severity=0
            set:'sc msg="["_$namespace_"] ERROR while compiling classes : "_$system.Status.GetErrorText(sc),severity=1
            do ##class(%SYS.System).WriteToConsoleLog(msg,verbose,severity)
            write:verbose msg,!
        }    
    }
    catch(ex) {
        set sc = ex.AsStatus()
        set msg="["_$namespace_"] error while executing "_..%ClassName(1)_":add("_name_","_value_") : "_ex.DisplayString(),severity=1
        write:verbose msg,!
        do ##class(%SYS.System).WriteToConsoleLog(msg,1,severity)
    }
    return sc
}

}

You can also check the results in the cconsole.log file:


10/05/16-19:39:11:250 (5744) 0 [SAMPLES] parameter DSINTERVAL=5 added to class DeepSee.Study.CityRainfall (via adm.param)
10/05/16-19:39:11:250 (5744) 0 [SAMPLES] parameter DSINTERVAL=5 added to class HoleFoods.Transaction (via adm.param)
10/05/16-19:39:11:250 (5744) 0 [SAMPLES] parameter DSINTERVAL=5 added to class News.DeepSee.NewsArticle (via adm.param)
10/05/16-19:39:11:515 (5744) 0 [SAMPLES] modified classes successfully compiled
Discussion (6)1
Log in or sign up to continue

Hi Evgeny, 

this code was written while upgrading to an async mirrored a DeepSee remote instance (originally based on a shadow server configuration + ECP access to ^OBJ.DSTIME global from DeepSee instance to production. It was before DSINTERVAL was created). 

Of course this sample can be modified to add/remove/modify any other parameter by modifying the query on %Dictionary.ParameterDefinition to filter any other parameter you are trying to add/remove/modify.