Question
· 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?

Discussion (9)2
Log in or sign up to continue

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 Status As %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,:""}

 

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") ==>

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

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:

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