How to use flags with ObjectScript?
-
06-07-2021 - |
Question
In C# this is allowed:
[Flags]
private enum PermissionType
{
Read = 0x0001,
Write = 0x0002,
Execute = 0x0004,
All = Read | Write | Execute
}
This allows:
private bool TestPerm(PermissionType p)
{
if( PermissionType.Read & p) return true; // user can read
if( PermissionType.Write & p) return true; // user can write
if( PermissionType.Execute & p) return true; // user can Execute
//etc
}
It can be called like this:
Testperm( PermissionType.Read | PermissionType.Write );
I know there is no enum DataType in ObjectScript, but I think a regular class with properties like this should work...
Class Sample.AcknowledgeType Extends %RegisteredObject
{
Property Read As %Integer [ InitialExpression = 1 ];
Property Write As %Integer [ InitialExpression = 2 ];
Property Execute As %Integer [ InitialExpression = 4 ];
Property All As %Integer [ InitialExpression = 7 ];
}
This is as far as I got. How do I write the TestPerm method?
Solution
It doesn't work like that.
Each property you define on the object uses a field in memory (and on disk if it is a persistent class) for each instance. So rather than defining a property with an initial expression, you would probably define a class parameter for read, write, execute, and all.
Also, the MUMPS language that Cache Object Script is a superset of doesn't let you do bit twiddling. There is an extension to the language that does allow this - the $BIT built-in function. This gets/sets the value of a bitstring at the specified location in the string.
Therefore, you could try:
Parameter READ=1;
Parameter WRITE=2;
Parameter EXECUTE=3;
Method TestPerm(Permissions as %String) as %Boolean
{
If $BIT(Permissions,..#READ) Quit 1
If $BIT(Permissions,..#WRITE) Quit 1
If $BIT(Permissions,..#EXECUTE) Quit 1
Quit 0
}
Without bitwise Boolean operators this isn't that handy. It gets worse.
You can't actually access the class parameters from outside the class without using the reflection capabilities in the %Dictionary package. That's too hard and too slow, so probably the best available choice is to expose the enumeration values with methods.
Method GetReadParameter()
{
Quit ..#READ
}
So now it's possible to write:
Set $BIT(Permissions,MyObject.GetReadParameter())
Set $BIT(Permissions,MyObject.GetWriteParameter())
Set HasPermission=MyObject.TestPerm(Permissions)
So, once we're done admiring the beauty of that code, it's probably time to admit that without native bitwise Boolean operators this C# idiom just isn't worth it. Instead just make a Permissions class, with Boolean properties Read,Write, and Execute. "All" can be a computed property.
If you really want you can make a Permissions class that has Read, Write, Execute, and All, each of which is Boolean and computed. You can write getter and setter methods that access a private property and use $BIT to set and read the value. But your Boolean logic would happen with the returned values, so rather than
Testperm( PermissionType.Read | PermissionType.Write );
you would do
If (myPermissions.Read || myPermissions.Write)