It is possible to define custom functions to be used within SystemWeaver path expressions. Such functions can be used in the same way as predefined functions, e.g., Count function.


Functions are defined at the top level of the script. Below are some examples of how to define custom functions and how to call them afterwards


Define a Function


Get Unchanged Items

Returns the unchanged Items in newVersionItems when comparing to prevVersionItems.  

<Function name="GetUnchangedItems" as="Items">
        <Parameter name="prevVersionItems" as="Items"/>
        <Parameter name="newVersionItems" as="Items"/>
        <!-- Unchanged Items are available in the set of Items from the previous version. -->
        <Value select="$newVersionItems[. in $prevVersionItems]"/>
    </Function>


Get Added Items

Returns the added Items in newVersionItems when comparing to prevVersionItems. 

<Function name="GetAddedItems" as="Items">
        <Parameter name="prevVersionItems" as="Items"/>
        <Parameter name="newVersionItems" as="Items"/>      
        <!-- Added Items have AncestorHandles that are not part of the Items in the previous version. -->
        <Value select="$newVersionItems[not AncestorHandle in $prevVersionItems.Select(AncestorHandle)]"/>
    </Function>    


Get Removed Items

Returns the removed Items in prevVersionItems when comparing to newVersionItems.

 <Function name="GetRemovedItems" as="Items">
        <Parameter name="prevVersionItems" as="Items"/>
        <Parameter name="newVersionItems" as="Items"/>
        <!-- Removed Items are available in the set of Items from the previous version but not in the new one. -->
        <!-- Use AncestorHandle when filtering to not get false positives on new versions. -->
        <Value select="$prevVersionItems[not AncestorHandle in $newVersionItems.Select(AncestorHandle)]"/>
    </Function>


Get Updated Items

Returns the updated Items in newVersionItems when comparing to prevVersionItems.

<Function name="GetUpdatedItems" as="Items">
        <Parameter name="prevVersionItems" as="Items"/> 
        <Parameter name="newVersionItems" as="Items"/>    
        <!-- Updated requirements have AncestorHandles that are available in the set of Items from the previous version, but Handles that are not. -->
        <Value select="$newVersionItems[not . in  $prevVersionItems and  AncestorHandle in $prevVersionItems.Select(AncestorHandle)]"/>
    </Function>


Get Previous Versions

Returns an item and it's previous versions, if there are any.

<Function name="GetPreviousVersions" as="Items">
    <Parameter name="p1" as="Items"/>  
    <Parameter name="p2" as="Items"/> 
    <Choose>
     <!--Checks if the version is the first version-->
      <When test="$p1.Handle != AncestorHandle ">
        <Value select="PreviousVersions($p1.PrevVersion, $p1 union $p2)"/> 
      </When>
      <Otherwise>
        <Value select="($p1 union $p2).OrderBy(Version)"/> 
      </Otherwise>
    </Choose>
  </Function>  


Is Duplicate Name

Determines whether the passed item has a unique name. It returns 'True' if the item name is unique and 'False' otherwise.

<Function name="IsDuplicateName" as="Boolean">
  <Parameter name="itemToCheck" as="Items"/>
  <Parameter name="allItems" as="Items"/>
  <Value select="$allItems[AncestorHandle !=  $itemToCheck.AncestorHandle][ Name = $itemToCheck.Name]"/>
</Function>


Is Valid Name

Determines whether the passed item has a valid name. This example uses a regular expression to validate the name which can be replaced by any other regular expression.

<Function name="IsValidName" as="Boolean">
  <Parameter name="itemToCheck" as="Items"/>
  <Value select="$itemToCheck.Name.Matches('^([a-zA-Z0-9_]*)$')"/>
</Function>


Is Integer

Determines whether the passed value is an integer. It returns 'True' if the value is integer and 'False' otherwise.

<Function name="IsInteger" as="Boolean">
  <Parameter name="ValueToCheck" as="Items"/>
  <!--Where @ATTSID is an attribute that contains the value which need to be tested-->
  <Value select="$ValueToCheck.Select(@ATTSID).Matches('^([+-]?[0-9]\d*|0)$')"/>
</Function>


Prettyprint FTA

Prints out an FTA (Fault Tree Analysis) in a text format with structure (indentation).

<Function name="prettyPrintFTA" as="String">
    <Parameter name="Level" as="String"/>
    <Choose>
        <!--2CET:Fault Event--> 
        <!--2CEV:External Event -->
        <When test="SID='2CET' or SID='2CEV'"> 
            <Value select="$Level + '- ' + Name"/>
        </When>
        <!--2CLO:Logic Or-->
        <When test="SID='2CLO'">   
            <Value select="$Level +  '- ' +  Name + ' (OR)' + NewLine + /2IFI.Select(prettyPrintFTA($Level + '    ')).Join(NewLine)"/>
        </When>  
        <!--2CLD:Logic And-->
        <When test="SID='2CLD'"> 
            <Value select="$Level +  '- ' +  Name + ' (AND)' + NewLine + /2IFI.Select(prettyPrintFTA($Level + '    ')).Join(NewLine)"/>
        </When>
    </Choose>
</Function>


Call a Function 

After defining a custom function, it will be global and can be used anywhere in a configuration. A custom function can be called by its name and parameters. For example, FunctionNameXYZ(parameterX, parameterY. More examples of how to call a function are shown below. 


Any Type of Configuration

<ForEach select="/ARPP[FunctionNameXYZ(.)]">
  ...
</ForEach>
<ForEach select="/ARPP">
  <If test="FunctionNameXYZ(.)">
  ...
  </If>
</ForEach>
<ForEach select="FunctionNameXYZ($P1, $P2)">
...
</ForEach>
<Choose>
    <When test="FunctionNameX($P1, $P2)">
      ...
    </When>
  <When test="FunctionNameY($P1, $P2)">
      ...
    </When>
  <When test="FunctionNameZ($P1, $P2)">
      ...
    </When> 
    <Otherwise>
    ....
    </Otherwise>
</Choose>
<ForEach select="/SID.Select(FunctionName($P1))">
  ...
</ForEach>


Graph

<Node caption="#{?FunctionNameXYZ(.)}" />
<Edge from="FunctionNameX($P1)" to="FunctionNameY($P2)"/>
<Edge from="." to="." caption="FunctionNameXYZ(.).ToString"/> 


Grid

<TextColumn caption="Fixed text">
     <Value>#{?FunctionNameXYZ(.)}</Value>
 </TextColumn>
<ItemNameColumn width="200" caption="#{?FunctionNameXYZ(.)}" />


Report or Document

<Text>#{? FunctionNameXYZ(.)}</Text>
<Text>#{?/SID.Select(FunctionName(@ATTSID))}</Text>



Example Configuration

Pretty-Print FTA Function

<Report>
<Text>#{?prettyPrintFTA('')}</Text>

<Function name="prettyPrintFTA" as="String">
    <Parameter name="Level" as="String"/>
    <Choose>
        <!--2CET:Fault Event--> 
        <!--2CEV:External Event -->
        <When test="SID='2CET' or SID='2CEV'"> 
            <Value select="$Level + '- ' + Name"/>
        </When>
        <!--2CLO:Logic Or-->
        <When test="SID='2CLO'">   
            <Value select="$Level +  '- ' +  Name + ' (OR)' + NewLine + /2IFI.Select(prettyPrintFTA($Level + '    ')).Join(NewLine)"/>
        </When>  
        <!--2CLD:Logic And-->
        <When test="SID='2CLD'"> 
            <Value select="$Level +  '- ' +  Name + ' (AND)' + NewLine + /2IFI.Select(prettyPrintFTA($Level + '    ')).Join(NewLine)"/>
        </When>
    </Choose>
</Function>

</Report>

Example Result