Question Davi Massaru Teixeira Muta · Mar 29, 2020

how to create one VALUELIST from a class parameters ?

Hello everyone!

I have an abstract class representing the possible inputs for an Enum field, in the following way: 

Class system.dto.sector.SectorStatusEnum  [ Abstract ]{Parameter Active = 1;Parameter Inactive = 2;Parameter Production = 3;Parameter Upkeep = 4;}

I need to create a persistent class referencing the abstract class in the status field, so that the result of the operation is the same as the example:

Class datas.TblSector Extends %Persistent{Property Description As %String( MAXLEN = 100 ) [ Required ];Property Status As %String(VALUELIST=",1,2,3,4", DISPLAYLIST=", Active, Inactive, Production, Upkeep") [ Required ];


}

Can someone help me pls?

Comments

Robert Cemper · Mar 30, 2020

PARAMETER and DISPLAYLIST are both compiler directives and you can't mix them.

But you may workaround it by writing your own pair of DisplayToLogical /  LogicalToDisplay ClassMethods for this property´.


Parameter Active = 1;
Parameter Inactive =2;
Parameter Production = 3;
Parameter Upkeep 4;
/// DISPLAYLIST = ", Active, Inactive, Production, Upkeep",
Property StatusAs %String(VALUELIST = ",1,2,3,4") [ Required ];
ClassMethod StatusDisplayToLogical(%val) As %String
{ Quit $case(%val,..#Active:1,..#Inactive:2,..#Production:3,..#Upkeep:4,:""}
ClassMethod StatusLogicalToDisplay(%val) As %String
Quit $case(%val,1:..#Active,2:..#Inactive,3:..#Production,4:..#Upkeep,:""}

 
0
Davi Massaru Teixeira Muta  Mar 30, 2020 to Robert Cemper

Is there a function that returns a string or list with all the parameters of the class?

0
Robert Cemper  Mar 30, 2020 to Davi Massaru Teixeira Muta

Not as string.
Parameters are stored as sub-object with the class object in  %Dictionary.* classes.
And serve as Information for the code to be compiled.

0
Julius Kavay  Mar 30, 2020 to Davi Massaru Teixeira Muta

not a built-in, but you can easily create one
 

ClassMethod ParamList() [ CodeMode = objectgenerator ] As %List
{
set params=""
for i=1:1:%class.Parameters.Count() set params=params_$lb(%class.Parameters.GetAt(i).Name)
do %code.WriteLine($c(9)_"quit """_params_"""")
} 

ClassMethod ParamString() As %String
{
quit $listtostring(..ParamList())
}
0
Davi Massaru Teixeira Muta  Mar 30, 2020 to Julius Kavay

Thanks !

Is possible to use the return of the Method to build the VALUELIST ? 

Or other property with the same purpose?

0
Julius Kavay  Mar 30, 2020 to Davi Massaru Teixeira Muta

Do I understand you right, you want to get the Value of a VALUELIST as a return value of a method? If yes, then the answer is yes.

Class Some.Class

{

Property Status As %String  (VALUELIST = ",1,2,3,4"); 

Property Rating As %String(VALUELIST = ",Bad,Good,Excellent");

/// For the Status property only
ClassMethod StatusValues() As %String [ CodeMode = objectgenerator ]
{
 for i=%class.Properties.Count():-1:0 if i,%class.Properties.GetAt(i).Name="Status" quit

 set val=$select(i:%class.Properties.GetAt(i).Parameters.GetAt("VALUELIST"), 1:"")

 do %code.WriteLine($c(9)_"quit """_val_"""")
} 

/// For all properties with a VALUELIST parameter

ClassMethod Values(prop) [ CodeMode = objectgenerator ]
{
 set sel=""
 for i=1:1:%class.Properties.Count() {
     set val=%class.Properties.GetAt(i).Parameters.GetAt("VALUELIST")
     set:val]"" sel=sel_""""_%class.Properties.GetAt(i).Name_""":"""_val_""", "
 }
 do %code.WriteLine($c(9)_"quit $case(prop,"_sel_":"""")")
}

}

And a few examples...

Write ##class(Some.Class).StatusValues()  ==> ,1,2,3

Write ##class(Some.Class).Values("Status") ==> ,1,2,3

Write ##class(Some.Class).Values("Rating") ==> Bad,Good,Excellent

Write ##class(Some.Class).Values("OtherProperty") ==>

0
Eduard Lebedyuk  Mar 31, 2020 to Julius Kavay

Alternatively, %Dictionary package macros can be used:

ClassMethod Values(class = {$classname()}, property) As %Status  [ CodeMode = expression]
{
$$$defMemberArrayGet(class,$$$cCLASSproperty,property,$$$cPROPparameter,"VALUELIST")
}

Also, you can find object from list without explicitly iterating the whole thing:

set i = %class.Properties.FindObjectId(%class.Name _ "||" _ "Status")

instead of:

for i=%class.Properties.Count():-1:0 if i,%class.Properties.GetAt(i).Name="Status" quit
0
Cristiano Silva · Mar 31, 2020

Hi Davi,

A simplest way is creating a datatype class:

Class system.dto.sector.SectorStatusEnum Extends %Integer [ ClassType = datatype ]{
Parameter DISPLAYLIST = ",Active,Inactive,Production,Upkeep,NewValue";
Parameter VALUELIST = ",1,2,3,4,5";}

And use the datatype in your class:

Class system.dto.sector.Test Extends %Persistent{Property SectorStatus As SectorStatusEnum;

}

Example:

0
Davi Massaru Teixeira Muta  Mar 31, 2020 to Cristiano Silva

Hello everyone !

I thank the help of all!

with everyone's help, it was possible to create a property with the same behavior as VALUE LIST from the parameters of a class. 

below is the test code:

First create the abstraction

Class ing.shared.abstracts.AbstractEnum [ Abstract ]{
ClassMethod BuildValueList() As %String{   Set valueList = ","_..GetValuesOfParametersString()   Return valueList} 
ClassMethod BuildDisplayList() As %String{   Set displayList = ","_..GetParametersString()   Return displayList}

ClassMethod GetValuesOfParameters(){   Set parametersList = ..GetParameters()   Set valueList= $lb("")   For i=1:1:$LISTLENGTH(parametersList){      Set value = $PARAMETER($CLASSNAME(),$LIST(parametersList,i))      Set $LIST(valueList,i) = value   }   Return valueList}
ClassMethod GetParameters() [ CodeMode = objectgenerator ]{   Set parametersClass=""   For i=1:1:%class.Parameters.Count(){      Set parametersClass=parametersClass_$LISTBUILD(%class.Parameters.GetAt(i).Name)   }   Do %code.WriteLine($char(9)_"Return """_parametersClass_"""")}

ClassMethod GetParametersString() As %String{   Return $listtostring(..GetParameters())}

ClassMethod GetValuesOfParametersString() As %String{   Return $listtostring(..GetValuesOfParameters())}
}

Second I created the class with the parameters, containing extension of the abstract class

Class ing.dto.AbstractionItemSectorStatus Extends ing.shared.abstracts.AbstractEnum{Parameter Active = 1;Parameter Inactive = 2;Parameter Production = 3;Parameter Upkeep = 4;}

Create a datatype class referencing a parameter class in your property:

Class ing.dataMap.DataTypeSectorStatusEnum Extends %Integer [ ClassType = datatype ]{

Parameter DISPLAYLIST = {##class(ing.dto.AbstractionItemSectorStatus).BuildDisplayList()};

Parameter VALUELIST = {##class(ing.dto.AbstractionItemSectorStatus).BuildValueList()};}

And finally create a  Persistent class:

Class ing.dataMap.TblSector Extends %Persistent{Property Description  As %String;Property SectorStatus As DataTypeSectorStatusEnum;}

This architecture can be useful for future code maintenance, creating or changing new abstract classes

0