/// v 1.3
/// Server side Interface for node-red-contrib-iris
Class Node.IRISInterface [ Abstract ]
{
///
///
///
/// Creates a new IRIS Class.
///
/// - namespace: The namespace where you want to create the class.
/// - package: The package name of the class.
/// - className: The name of the class.
/// - properties: The properties names of the class, written as a String list.
/// - propTypes: The types of the properties, written as a String list and in same order as properties.
/// - superClasses: Superclasses of the class, written as a String list. (%Persistent and %JSON.Adaptor are always superclasses)
///
/// Needs to compile the class afterwards.
Use CompileClass or use DO $SYSTEM.OBJ.Compile("className")
/// Old method for node-red-contrib-iris 1.0.2 or before!
///
ClassMethod CreateClass(namespace As %String = 0, package As %String, className As %String, properties As %String = "", propTypes As %String = "", superClasses As %String = "") As %Status
{
SET class = package_"."_className
//Set namespace
SET beforeNS = $NAMESPACE
SET:(namespace = 0) namespace = $NAMESPACE
ZN namespace
SET exists = ##class(%Dictionary.CompiledClass).%ExistsId(class)
if exists{
SET ex = ##class(%Exception.General).%New("Class "_class_" already exists!")
ZN beforeNS
throw ex
}
//Define Class
SET cdef = ##class(%Dictionary.ClassDefinition).%New(class)
if $SYSTEM.Status.IsError(cdef) {
DO $system.Status.DecomposeStatus(%objlasterror,.Err)
throw Err
}
//Add superclasses
SET:(superClasses '= "") superClasses = ","_superClasses
SET cdef.Super = "%Persistent"_superClasses
// add Properties
SET propLst = $LISTFROMSTRING(properties)
SET typeLst = $LISTFROMSTRING(propTypes)
for i = 1:1:$LL(propLst){
//Get Type of Property
if i > $LL(typeLst){
SET type = "%String" //Set type to String if no type is given
}
else{
SET type = $LG(typeLst, i)
}
//SET exist=##class(%Dictionary.CompiledClass).%ExistsId(type)
//Insert Property
SET pdef = ##class(%Dictionary.PropertyDefinition).%New(className_":"_$LG(propLst,i))
if $SYSTEM.Status.IsError(pdef) {
DO $system.Status.DecomposeStatus(%objlasterror,.Err)
throw Err
}
//d pdef.Parameters.SetAt("AGE()", "POPSEC")
DO cdef.Properties.Insert(pdef)
SET pdef.Type = type
//SET pdef.Required = 1
//d pdef.ParameterSet("MAXVAL = 100")
}
//Save class
DO cdef.%Save()
//Set old namespace
ZN beforeNS
return $$$OK
}
///
/// Creates a new IRIS Class.
///
/// - namespace: The namespace where you want to create the class.
/// - package: The package name of the class.
/// - className: The name of the class.
/// - superClasses: Superclasses of the class, written as a String list. (%Persistent and %JSON.Adaptor are always superclasses)
/// - propertiesJSON: A JSON String defining the properties of the class.
/// - methodsJSON: A JSON String defining the methods of the class.
///
/// Needs to compile the class afterwards.
Use CompileClass or use DO $SYSTEM.OBJ.Compile("className")
/// New method for node-red-contrib-iris 1.0.3 or later!
///
ClassMethod CreateClassNew(namespace As %String = 0, package As %String, className As %String, superClasses As %String = "", propertiesJSON As %String = "", methodsJSON As %String = "") As %Status
{
SET class = package_"."_className
//Set namespace
SET beforeNS = $NAMESPACE
SET:(namespace = 0) namespace = $NAMESPACE
ZN namespace
SET exists = ##class(%Dictionary.CompiledClass).%ExistsId(class)
if exists{
SET ex = ##class(%Exception.General).%New("Class "_class_" already exists!")
ZN beforeNS
throw ex
}
//Define Class
SET cdef = ##class(%Dictionary.ClassDefinition).%New(class)
if $SYSTEM.Status.IsError(cdef) {
DO $system.Status.DecomposeStatus(%objlasterror,.Err)
throw Err
}
//Add superclasses
SET:(superClasses '= "") cdef.Super = superClasses
if propertiesJSON '= ""{
SET propDA = ##class(%DynamicArray).%FromJSON(propertiesJSON)
//SET i = propDA.%GetIterator()
SET i = propDA.%Pop()
while i '= ""{
SET pdef = ##class(%Dictionary.PropertyDefinition).%New(className_":"_i.name)
if $SYSTEM.Status.IsError(pdef) {
DO $system.Status.DecomposeStatus(%objlasterror,.Err)
throw Err
}
DO cdef.Properties.Insert(pdef)
if i.%IsDefined("type"){
SET type = i.type
}
else{
SET type = "%String"
}
SET pdef.Type = type
if i.%IsDefined("required"){
SET pdef.Required = i.required
}
if i.%IsDefined("parameters"){
SET params = i.parameters
SET j = params.%Pop()
while j '= ""{
do pdef.Parameters.SetAt(j.value, j.name)
SET j = params.%Pop()
}
}
SET i = propDA.%Pop()
}
}
if methodsJSON '= ""{
SET methDA = ##class(%DynamicArray).%FromJSON(methodsJSON)
SET i = methDA.%Pop()
while i '= ""{
SET mdef = ##class(%Dictionary.MethodDefinition).%New(className_":"_i.name)
if $SYSTEM.Status.IsError(mdef) {
DO $system.Status.DecomposeStatus(%objlasterror,.Err)
throw Err
}
if i.%IsDefined("parameters"){
do mdef.FormalSpecSet(i.parameters)
}
DO cdef.Methods.Insert(mdef)
if i.%IsDefined("returnType"){
SET mdef.ReturnType = i.returnType
}
if i.%IsDefined("classMethod"){
SET mdef.ClassMethod = i.classMethod
}
if i.%IsDefined("body"){
SET mdef.Implementation.LineTerminator = $c(13,10)
SET l = $LFS(i.body,";")
for i = 1:1:$LL(l){
DO mdef.Implementation.WriteLine(" "_$LG(l,i)_" ")
}
//DO mdef.Implementation.Write(i.body)
}
SET i = propDA.%Pop()
}
}
//Save class
DO cdef.%Save()
//Set old namespace
ZN beforeNS
return $$$OK
}
///
/// Compiles a Class.
///
/// - namespace: The namespace containing the given class
/// - package: The package of the given class
/// - className: the Name of the class
///
///
ClassMethod CompileClass(namespace As %String, package As %String, className As %String) As %Status
{
#dim tEx as %Exception.SystemException
#dim tSc as %Status = $$$OK
#dim class as %String = package_"."_className
//Set namespace
SET bns = $NAMESPACE
ZN namespace
//compile
try{
$$$ThrowOnError($System.OBJ.Compile(class, "/Display=none"))
}
catch tEx {
SET tSc = tEx.AsStatus()
}
ZN bns
return tSc
}
///
/// Deletes a Class.
///
/// - namespace: The namespace containing the given class
/// - package: The package of the given class
/// - className: the Name of the class
///
///
ClassMethod DeleteClass(namespace As %String, package As %String, className As %String) As %Status
{
SET class = package_"."_className
//Set namespace
SET bns = $NAMESPACE
ZN namespace
SET exists = ##class(%Dictionary.CompiledClass).%ExistsId(class)
if 'exists{
SET ex = ##class(%Exception.General).%New("Class "_class_" does not exists!")
ZN bns
throw ex
}
//delete
try{
SET status = $System.OBJ.Delete(class, "/Display=none")
}
catch e {
throw e
}
ZN bns
return status
}
///
/// Checks if the class exists.
///
/// - namespace: The namespace where to look in
/// - className: The name of the class
///
///
ClassMethod CheckIfClassExists(namespace As %String, className As %String) As %Status
{
//Set namespace
SET bns = $NAMESPACE
ZN namespace
SET exists = ##class(%Dictionary.CompiledClass).%ExistsId(className)
ZN bns
return exists
}
///
/// Executes a SQL Insert Statement
///
/// - sql: The sql Statement
/// - params: The Parameter for the Statement
/// - namespace: The Namespace in which the Class is
///
///
ClassMethod exInsert(sql As %String, params As %String = "", namespace As %String = 0) As %Status
{
#dim tEx as %Exception.SystemException
#dim tSc as %Status = $$$OK
#dim tStmt as %SQL.Statement = ##class(%SQL.Statement).%New()
if namespace = 0{
SET namespace = $NAMESPACE
}
SET beforeNamespace = $NAMESPACE
ZN namespace
//parseStringToArray
SET list = $LISTFROMSTRING(params)
SET values = $LL(list)
for i = 0:1:$LL(list)
{
SET values(i) = $LG(list,i)
SET values(i) = $REPLACE(values(i), "~",",")
}
s b = 1
//Make Execute
try{
SET tStmt.%SelectMode = 1
$$$ThrowOnError(tStmt.%Prepare(sql))
SET result = tStmt.%Execute(values...)
if result.%SQLCODE < 0{
SET tSc = 0
}
}
catch tEx{
SET tSc = tEx.OnAsStatus()
}
ZN beforeNamespace
return tSc
}
///
/// Inserts a JSON Object into IRIS
///
/// - namespace: The Namespace of the Classes
/// - JSONString: The JSON String of the Object
/// - obj: Only for recursively purpose
/// - recursiveBeginning: Only for recursively purpose
///
///
ClassMethod InsertObjectOriented(namespace As %String = 0, JSONString As %String = "", obj As %DynamicAbstractObject = -1, recursiveBeginning As %Integer = 1)
{
if recursiveBeginning = 1{
SET beforeNamespace = $NAMESPACE
ZN namespace
}
if obj = -1{
try{
//Convert to Dynamic Abstract Object
SET obj = ##class(%DynamicAbstractObject).%FromJSON(JSONString)
}catch ex{
if recursiveBeginning = 1{
//Return Message to Node-Red
RETURN "Cannot convert JSON String "_ex.AsSystemError()
}else{
//Throw for lower recursive
THROW ##class(%Exception.SystemException).%New("CANNOT CONVERT TO JSON STRING","999",,"Cannot convert JSON String: "_ex.AsSystemError())
}
}
}
SET iter = obj.%GetIterator() //Get Iterator
SET className = obj.className //Get className
try{
SET o = $SYSTEM.OBJ.New(className) //Make new Instance of class
}catch ex{
if recursiveBeginning = 1{
//Return Message to Node-Red
RETURN className_" does not exists: "_ex.AsSystemError()
}else{
//Throw for lower recursive
THROW ##class(%Exception.SystemException).%New("CLASS DOES NOT EXISTS","999",,className_" does not exists: "_ex.AsSystemError())
}
}
//Check if id Property exists and then return already existing object
if (obj.%IsDefined("id")){
SET id = obj.id
RETURN $SYSTEM.OBJ.New(className).%OpenId(id)
}
//Iterate through JSON Object
while iter.%GetNext(.key, .value, .type ) {
if key = "className"{
CONTINUE
}
//If Property is an object go recursive with that object
if type = "object"{
try{
SET value = ##class(Node.IRISInterface).InsertObjectOriented(,value,0)
}catch ex{
if recursiveBeginning = 1{
//Return Message to Node-Red
RETURN ex.AsSystemError()
}else{
//Throw for lower recursive
THROW ex
}
}
}
SET $PROPERTY(o,key) = value //Set Property
}
try{
DO o.%Save() //Save object
}catch ex{
if recursiveBeginning = 1{
//Return Message to Node-Red
RETURN "Cannot save class "_ex.AsSystemError()
}else{
//Throw for lower recursive
THROW ##class(%Exception.SystemException).%New("CANNOT SAVE CLASS","999",,"Cannot save class: "_ex.AsSystemError())
}
}
if recursiveBeginning = 1{
ZN beforeNamespace
RETURN 1 //Return ok to Node Red
}
else{
RETURN o //Return object for lower recursive
}
}
ClassMethod ExecArray(sql As %String, params As %String = "", namespace As %String = 0) As %String
{
#dim tEx as %Exception.SystemException
#dim tSc as %Status = $$$OK
#dim tStmt as %SQL.Statement = ##class(%SQL.Statement).%New()
//Set namespace
if namespace = 0{
SET namespace = $NAMESPACE
}
SET beforeNamespace = $NAMESPACE
ZN namespace
//parseStringToArray
//parse the parameters into an array
SET list = $LISTFROMSTRING(params)
SET values = $LL(list)
for i = 0:1:$LL(list)
{
SET values(i) = $LG(list,i)
SET values(i) = $REPLACE(values(i), "~",",")
}
try{
//Make Execute
SET tStmt.%SelectMode = 1
$$$ThrowOnError(tStmt.%Prepare(sql))
SET result = tStmt.%Execute(values...)
if result.%SQLCODE < 0{
ZN beforeNamespace
throw result.%Message
}
//Parse to JSON
SET colList = result.%GetMetadata().columns
SET cols = ""
SET colArray = ##class(%DynamicArray).%New()
for i = 1:1:colList.Size{
SET cols(i) = colList.GetAt(i).colName
DO colArray.%Push(cols(i))
}
SET a = $LB(colArray.%ToJSON())
//iterate through results
while result.%Next(){
SET obj = ##class(%DynamicArray).%New()
//iterate through coulmns in result
for i = 1:1:colList.Size{
SET value = result.%Get(cols(i))
DO obj.%Push(value)
}
SET a = a_$LB(obj.%ToJSON())
}
}
catch tEx{
RETURN tEx.AsStatus()
}
ZN beforeNamespace
RETURN "["_$LISTTOSTRING(a)_"]"
}
///
/// Executes a SQl Query. params (optional) are the values of a paramerized query
///
/// - sql: The SQL Query
/// - params: The parameter of the Query in form of a String-List
/// - namespace: The namespace in which the Query should be Executed
///
/// Returns the result in form of a JSON-String.
///
ClassMethod Exec(sql As %String, params As %String = "", namespace As %String = 0) As %String
{
#dim tEx as %Exception.SystemException
#dim tSc as %Status = $$$OK
#dim tStmt as %SQL.Statement = ##class(%SQL.Statement).%New()
//Set namespace
if namespace = 0{
SET namespace = $NAMESPACE
}
SET beforeNamespace = $NAMESPACE
ZN namespace
//parseStringToArray
//parse the parameters into an array
SET list = $LISTFROMSTRING(params)
SET values = $LL(list)
for i = 0:1:$LL(list)
{
SET values(i) = $LG(list,i)
}
try{
//Make Execute
SET tStmt.%SelectMode = 1
$$$ThrowOnError(tStmt.%Prepare(sql))
SET result = tStmt.%Execute(values...)
if result.%SQLCODE < 0{
ZN beforeNamespace
THROW result.%Message
}
//Parse to JSON
SET colList = result.%GetMetadata().columns
SET cols = ""
for i = 1:1:colList.Size{
SET cols(i) = colList.GetAt(i).colName
}
SET a = ""
//iterate through results
while result.%Next(){
SET obj = ##class(%DynamicObject).%New()
//iterate through coulmns in result
for i = 1:1:colList.Size{
SET value = result.%Get(cols(i))
//d obj.%Set(value)
DO obj.%Set(cols(i),value)
}
SET a = a_$LB(obj.%ToJSON())
}
}
catch tEx{
return tEx.AsStatus()
}
ZN beforeNamespace
///REST Service write über standard io
return "["_$LISTTOSTRING(a)_"]"
}
ClassMethod ExecProduction(sql As %String, params As %String = "", namespace As %String = 0) As %List
{
#dim tEx as %Exception.SystemException
#dim tSc as %Status = $$$OK
#dim tStmt as %SQL.Statement = ##class(%SQL.Statement).%New()
//Set namespace
if namespace = 0{
SET namespace = $NAMESPACE
}
SET beforeNamespace = $NAMESPACE
ZN namespace
//parseStringToArray
//parse the parameters into an array
SET list = $LISTFROMSTRING(params)
SET values = $LL(list)
for i = 0:1:$LL(list)
{
SET values(i) = $LG(list,i)
}
try{
//Make Execute
SET tStmt.%SelectMode = 1
$$$ThrowOnError(tStmt.%Prepare(sql))
SET result = tStmt.%Execute(values...)
if result.%SQLCODE < 0{
ZN beforeNamespace
throw result.%Message
}
//Parse to JSON
//DO result.%NormalizeObject()
SET colList = result.%GetMetadata().columns
SET cols = ""
for i = 1:1:colList.Size{
SET cols(i) = colList.GetAt(i).colName
}
SET a = ""
//iterate through results
while result.%Next(){
SET obj = ##class(%DynamicObject).%New()
//iterate through coulmns in result
for i = 1:1:colList.Size{
SET value = result.%Get(cols(i))
DO obj.%Set(cols(i),value)
}
SET a = a_$LB(obj.%ToJSON())
}
}
catch tEx{
return tEx.AsStatus()
}
ZN beforeNamespace
///REST Service write über standard io
return "["_$LISTTOSTRING(a)_"]"
}
}