Example window calculations

This section contains some further examples of window calculations with explanations of how they work. First, however, there is an extended version of the requirement sentence and a corresponding template calculation with placeholders. You can use this to help you to write basic calculations.

When the TRIGGER_FIELD on the TRIGGER_OBJECT is set to VALUE, I want to change the PROPERTY of TARGET to true/false.

The calculation that corresponds to this requirement sentence is:

Copy
import System
static def GetAttributeValue(Incident):
    PropertyState = false
    if TRIGGER_OBJECT.TRIGGER_FIELD != null and TRIGGER_OBJECT.TRIGGER_FIELD._Title == 'VALUE':    
        PropertyState = true    
    return String.Format(":SetPROPERTY(TARGET, {0});", PropertyState)

Replacing the placeholders from the requirement sentence in the calculation, and then adding TRIGGER_FIELD to the Dependencies panel in the Calculation editor gives you the required calculation. We also recommend that you replace all references to "PropertyState" with a more descriptive name for the variable.

The rest of this section gives examples based on this calculation and explains its logic. Later examples extend the calculation further.

The indentations in these calculations are very important, and set the scope of the functions. Therefore, if you copy examples from this document, make sure that the correct indentations are maintained when you paste them into the calculation editor.

Using if statements to reset values

The following example extends the example given in Setting up the window calculations so that the Impact field is set to be non-mandatory and becomes mandatory only if the Urgency field is set to Urgent. If the field is cleared (set to null), or set to another value, then the Impact field is set to be non-mandatory again.

Our requirement sentence for this is:

When Urgency is set to Urgent, I want to change SetMandatory of Impact to true.

This tells us that the trigger field is Urgency, the target attribute is Impact, and the window function is :SetMandatory(,).

A good structure for a Window calculation is:

  • define a variable at the start that specifies the typical true or false value for the window function
  • then construct a statement that changes the variable when the appropriate values are selected
  • finally return the Window function using the variable to set its true/false parameter

For example:

Copy
import System
static def GetAttributeValue(Incident):
    MandatoryUrgency = false
    if Incident._IncidentUrgency != null and Incident._IncidentUrgency._Title == 'Urgent':    
        MandatoryUrgency = true
    return String.Format(":SetMandatory(_Impact, {0});", MandatoryUrgency)

The third, fourth, and final lines have a single indent; line five has a double indent.

Line three creates a variable called MandatoryUrgency and sets its value to false. This is the most common, default value for the calculation.

Line four tests to see if the Urgency is set to Urgent (Incident._IncidentUrgency._Title == 'Urgent'). Note that before the calculation can test the value of the attribute Incident._IncidentUrgency._Title, the calculation language requires us to test that the attribute's object is not null (Incident._IncidentUrgency != null).

If line four is true, and the Urgency is not null, and is set to Urgent, then line five runs and sets the value of the variable MandatoryUrgency to true.

Finally, line six runs and sets the value of the calculation attribute. Because we are referencing a variable, the calculation language requires us to generate the return string using a String.Format function. This is of the form String.Format("function(attribute, {0});", variable) – the {0} is replaced by the variable when the string is generated, to give us :SetMandatory(_Impact,MandatoryUrgency);. By default, MandatoryUrgency is false, so the Impact field is not mandatory. However, if the Urgency is set to Urgent, then the conditions specified in line four are met, and line five runs. This then sets the variable MandatoryUrgency to true, so the Impact field becomes mandatory.

Notice that lines three and five use a single equals sign = whereas line four uses two equals signs ==.
= means "make this equal to", whereas == means "does this equal?"

Updating two fields with one calculation

The next example shows how you can update two fields using a single calculation, using a similar calculation to that in the previous example. In this example, the Configuration Item and Configuration Item Type fields appear only if the Category is set to Hardware.

Our requirement sentence for this is:

When Category is set to Hardware, I want to change SetHidden of Configuration Item AND Configuration Item Type to false.

This tells us that the trigger field is Category, the target attributes are Configuration Item AND Configuration Item Type, and the window function is :SetHidden(,).

Copy
import System
static def GetAttributeValue(Incident):
    HideCI = true
    if Incident.Category != null and Incident.Category.FullName == 'Hardware':    
        HideCI = false
return String.Format(":SetHidden(ConfigurationItemType,{0});:SetHidden(ConfigurationItem,{1});", HideCI, HideCI)

The third, fourth, and sixth lines have a single indent; line five has a double indent. The long line six appears on a single line in the calculation editor.

Line three sets the variable HideCI to true.

Line four tests that the Category is not null and is set to Hardware.

If line four is true, then line five runs and sets HideCI to false.

Finally, line six runs and sets the value of the calculation attribute to String.Format(":SetHidden(ConfigurationItemType,{0});:SetHidden(ConfigurationItem,{1});", HideCI, HideCI). By default, HideCI is true, so the ConfigurationItemType and ConfigurationItem fields are hidden. However, if the Category is set to Hardware, then the conditions specified in line four are met, and line five runs. This then sets the variable HideCI to false, so the ConfigurationItemType and ConfigurationItem fields become visible.

When you use String.Format to return more than one function that uses variables, you refer to the variables in the function as numbers in curly brackets and then add the variables in order afterward. For example:

String.Format("function(attribute, {0});function(attribute, {1});function(attribute, {2});", variable 0, variable1, variable 2)

:SetHidden also shows and hides the label associated with the target attribute. However, you cannot use :SetHidden for static labels added from the Controls tree in Window Manager.

Using different functions with one trigger

The previous examples have always returned just one Windows function: either changing the mandatory state of one or more fields, or changing the hidden state. This example shows how you can update two different functions using a single calculation. This example extends the previous example, with the Configuration Item and Configuration Item Type fields appearing if the Category is set to Hardware, but also with the Configuration Item Type being made mandatory.

Our requirement sentence for this is:

When Category is set to Hardware, I want to change SetHidden of Configuration Item AND Configuration Item Type to false AND to change SetMandatory of Configuration Item Type to true.

This tells us that the trigger field is Category, the target attributes are Configuration Item and Configuration Item Type, and the window functions are :SetHidden(,) and SetMandatory(,).

Copy
import System
static def GetAttributeValue(Incident):
    HideCI = true
    MandatoryCI = false
    if Incident.Category != null and Incident.Category.FullName == 'Hardware':
        HideCI = false
        MandatoryCI = true
    return String.Format(":SetHidden(ConfigurationItemType,{0});:SetHidden(ConfigurationItem,{1});:SetMandatory(ConfigurationItemType,{2});", HideCI, HideCI, MandatoryCI)

The third, fourth, fifth, and eighth lines have a single indent; lines six and seven have a double indent. The long line eight appears on a single line in the calculation editor.

Line three sets the variable HideCI to true – by default we want the CI and CI Type fields to be hidden.

Line four sets the variable MandatoryCI to false – by default we want the CI Type field to be not mandatory.

If line five is true, then both lines six and seven run and set HideCI to false and MandatoryCI to true. Both of these lines run because they have the same indentation in the calculation.

Finally, the long line eight runs and passes the value of HideCI to the first two functions, and the value of MandatoryCI to the third function.

Because you are sending the same variable to the first two functions, you could rewrite line eight as:
return String.Format(":SetHidden(ConfigurationItemType,{0});:SetHidden(ConfigurationItem,{0});:SetMandatory(ConfigurationItemType,{1});", HideCI, MandatoryCI)

Using different functions based on the values of one trigger

This example shows how you can use a different function depending on the value selected in the trigger attribute. If the Priority is set to High, then the Reason field is made mandatory and editable; if the Priority is set to Low, then the Reason field is made non-mandatory and read-only; otherwise, the Reason field is left in its default state.

This calculation needs an attribute with the Name set to _reason to be added to the Incident object.

Our requirement sentence for this is:

When Priority is set to High, I want to change SetMandatory of Reason to true AND for SetReadOnly of Reason to be false; when Priority is set to Low, I want to change SetReadOnly of Reason to true AND for SetMandatory of Reason to be false.

This tells us that the trigger field is Priority, the target attribute is Reason, and the window functions are SetMandatory(,) and SetReadOnly(,). We could also write:

At all other times, I want both SetMandatory and SetReadOnly of Reason to be false.

This tells us that the default value for both SetMandatory and SetReadOnly of Reason is false.

Copy
import System
static def GetAttributeValue(Incident):
    MandatoryReason = false
    ReadOnlyReason = false
    if Incident.Priority != null and Incident.Priority.Title == 'High':
        MandatoryReason = true
    elif Incident.Priority != null and Incident.Priority.Title == 'Low':
        ReadOnlyReason = true
    return String.Format(":SetMandatory(_reason, {0});:SetReadOnly(_reason, {1});", MandatoryReason, ReadOnlyReason)

The third, fourth, fifth, seventh, and ninth lines have a single indent; lines six and eight have a double indent. The long line nine appears on a single line in the calculation editor.

Line three sets the variable MandatoryReason to false – by default we want the Reason field to be not mandatory.

Line four sets the variable ReadOnlyReason to false – by default we want the Reason field to be read-only.

If line five is true, and the Priority field is set to High, then line six runs and sets MandatoryReason to true.

If line five is NOT true, then line seven runs. elif ("else if") lines run only if the preceding line is false. If this line is true, and the Priority field is set to Low, then line eight runs and sets ReadOnlyReason to true.

Finally, line nine runs using the set values of MandatoryReason and ReadOnlyReason.

This means that, by default, MandatoryReason and ReadOnlyReason are false, so the Reason field is neither mandatory nor read-only. If, however, the Priority is set to High, then MandatoryReason is true (lines five and six), but ReadOnlyReason is still false, so Reason is mandatory but not read-only. If the Priority is set to Low, then ReadOnlyReason is true (lines seven and eight), but MandatoryReason is false, so Reason is read-only but not mandatory.

Using dates in calculations

This example makes the Reason field mandatory if the date selected in the Date Required field is set to within seven days of the current date.

This calculation needs attributes with their Name set to _reason and _daterequired to be added to the Incident object. Remember not to update the same field with different calculations.

Our requirement sentence for this is:

When Date Required is set to within 7 days of today, I want to change SetMandatory of Reason to true.

This tells us that the trigger field is Date Required, the target attribute is Reason, and the window function is SetMandatory(,).

Copy

import System
static def GetAttributeValue(Incident):
    MandatoryReason = false
    if Incident._daterequired != null and Incident._daterequired < DateTime.Today.AddDays(7):
        MandatoryReason = true
    return String.Format(":SetMandatory(_reason,{0});", MandatoryReason)

The third, fourth, and final lines have a single indent; line five has a double indent.

Line three creates a variable called MandatoryReason and sets it to false – by default we want the Reason field to be not mandatory.

Line four uses a .Net Method called .AddDays to determine if the Date Required is less than today's date plus 7. If it is, then line five runs and sets MandatoryReason to true.

Line six then generates the appropriate SetMandatory function.

For more information about using .Net Methods in your calculations, see the Ivanti Community web site.