Configuration
There are several mechanisms used to configure this interface:
DML files
Database tables
Command line options
Once the dml files and configuration tables for a customer's initial configuration have gone into production, a knowledgeable user can make changes to the configuration, as business needs change. For example:
Change element tags and attribute names in input and output messages.
Remove obsolete elements and attributes.
Add new elements and attributes.
Change the format and contents of elements and attributes in output messages.
Change the transformation of data in input messages.
Alter business logic.
Change the contents of the tables that translate Oracle Utilities Network Management System values to and from equivalent values in the messages to and from the MDS.
Change the conditions that trigger the various messages sent to the MDS.
Alter the names of the MQSeries queue manager and queues.
The adapter needs to be restarted for configuration changes to take effect.
DML Files
DML files contain dml code that is compiled into internal data structures during initialization. Any errors in the dml files are logged, with the file names and line numbers that the errors were detected on. Any such errors cause initialization to fail. There is an off-line program that allows dml files to be checked before use.
A narrative about the various facilities is provided here. The details of the syntax and capabilities of dml are described below in the Appendices.
The main purpose of dml is to generate and process XML elements. The first few sections describe the generation of XML from Output Documents, but most of the facilities described can be used in Input Documents, which process XML. The discussion of Input Documents starts at section Input Elements and Attributes .
Output Elements and Attributes
In the following dml statement:
&Hello = world;
& identifies that the following string (Hello) is an element tag.
= assigns the element data.
world is a constant value.
; terminates the statement.
Resulting in the following element:
<Hello>world</Hello>
Optionally, to include a namespace prefix, add the namespace and a separator (^) before the local element tag. For example, adding the namespace prefix mds to the previous statement:
&mds^Hello = world;
generates the element
<mds:Hello>world</mds:Hello>
 
Similarly, the statement:
&Tag < attr1=1; attr2=two; > = "";
< > enclose a list of attributes and their values.
"" is an empty string.
generates the following empty element with two attributes:
<Tag attr1="1" attr2="two"/>
The statements:
&Tag < attr1=1; attr2=two; >
{
&SubTag1=SubData1;
&SubTag2=SubData2;
}
 
{} enclose a list of sub-elements.
generates the following element having two attributes and two sub-elements:
<Tag attr1="1" attr2="two">
<SubTab1>SubData1</SubTab1>
<SubTab2>SubData2</SubTab2>
</Tag>
External Data
So far, the elements and attributes discussed have contained only constant data. An example reading data from an event in an SRSoutput message is:
&EventDevice=$E.devAlias;
This assigns the alias (name) of the event's interrupting device to the element tagged 'EventDevice'. The '$' indicates that the following string is the name of an external data object. The 'E' indicates that the data is associated with an event object, the '.' separates the components of the name, and the 'devAlias' identifies the data field within the object. The names used for the fields of an event object are similar to the names of the corresponding fields in the Oracle Utilities Network Management System SRSoutput class.
Data obtained this way can be combined with other data using dml operators. For example:
&ExternalId = "NMS:" + $E.outageHdl.idx;
concatenates the constant string 'NMS:' (contained within quotes because of the non-alphanumeric character ':'), with the event's index (sometimes known as the Ticket Number). Assuming that the event's index was 1234, the following element would be generated:
<ExternalId>NMS:1234</ExternalId>
Variables
Sometimes the same data is to be assigned to more than one element, or intermediate result is to be used in more than one element. Variables are used to hold such intermediate results. For example:
@eid = "NMS:" + $E.outageHdl.idx;
&ExternalId = @eid;
&code = @eid + "%" + $E.devAlias;
would generate, assuming the device name was XFM1234567,
<ExternalId>NMS:1234</ExternalId>
<code>NMS:1234%XFM1234567</code>
The '@' indicates that the following string is the name of a variable. The '+' operator concatenates the string to the right with the string to the left.
SQL Select Statements
A SQL Select statement is used to read data from the database. For example, the statement:
sqlselect @type, @intDev | type_om, interrupt_dev_om |
picklist_info_upd_tr | "where ref_id=" | $E.outageHdl.idx;
sets variables 'type' and 'intDev' to the values in the 'type_om' and 'interrupt_dev_om' columns of the row in the 'picklist_info_upd_tr' table where the 'ref_id' column matches the current event's index.
The 'sqlselect' introduces the SQL select statement, and is followed by a list of variables that will be set to the contents of the columns in the database, separated by commas, and terminated by a vertical bar (|) as a separator. After the variables is a list of the columns to assign to the respective variables, separated by commas, and terminated by a vertical bar. The number of column names must match the number of variables. The column names are followed by the table or view name. The rest of the statement builds the 'where clause', by concatenating the values of all the remaining components. This syntax only supports a simple select syntax. More complicated select statements are built as a view on database tables, which the dml then accesses using this simpler syntax.
The table name can be a constant or the value of a variable, an external data field, a function call, or the result of the data manipulations, as described below.
If the table name is a constant, the columns are checked for validity at initialization time. If any of the columns specified are not in the table, an error message is output to the log, and initialization fails.
If the table name is not a constant, the columns are checked for validity at run time. If the table does not exist, all variables are set to their default values (described below), and, optionally, a debug message is output to the log. If a column is missing, the variable for the column is set to its default value, and, optionally, a debug message output to the log.
An important source of data relating to devices in the model is the facilities (or attribute) tables associated with various device classes (types). The name of the table for a device class is supplied by the 'classTable' function, which queries the Oracle Utilities Network Management System services for the table's name. Not all facilities tables have the same columns (for example fuses and transformers may have fuse sizes, while reclosers may not). This is the reason that the adapter does not regard a missing column at run time as a fatal error.
Some tables, for example the facilities tables described above, contain data that does not change very often, and can be regarded as remaining static. In this case, values only need to be read from these tables when the table name, or 'where clause' changes. Such tables are declared static by use of the 'static' keyword. For example:
 
sqlselect @devPhases, @fuseSize |
phase_designation, fuse_size |
static classTable($E.devHdl.cls) | "where h_idx = " | $E.devHdl.idx;
reads the 'phase_designation' and 'fuse_size' columns for the interrupting device for an outage.
If the select returns no rows, the variables are set to their default values. If the select statement returns one or more rows of the table, the values are taken from the first row returned. Subsequent rows are ignored in the initial implementation of the adapter.
Function Calls
Function calls have a number of uses, including:
Making Oracle Utilities Network Management System API calls.
Performing data manipulations not supported by the dml syntax.
Accessing the adapter's data.
Accessing other configuration data.
A simple example of truncating external data to 100 characters to match the length of strings expected by the MDS is:
&Address = substring($E.dispAddress, 0, 100);
the Address element is assigned 100 characters of the 'dispAddress' field from SRSoutput, starting at the beginning of the string (an offset of zero).
The various functions available are described in DML Function Calls.
Expressions
The values of the various data sources can be combined in expressions. Examples of the string concatenation operator '+' have been shown above. The other operators in the initial implementation involve boolean or logical values.
Boolean values are either true or false. Any non-empty string is considered true, while the empty string is false. Boolean operators return 'Y' when they evaluate to true and the empty string when false. The boolean operators are:
The equality operator '==': This compares two values for textual equality. For example abc == ab has a value of "" (false).
The inequality operator '!=': This compares two values for textual inequality. For example abc != abc has a value of "" (false).
The logical AND operator '&&': This is the union of two values, and has a value of true if and only if both values are true. For example, Y && Y has a value of Y (true).
The logical inclusive OR operator '||': This is the intersection of two values, and has a value of true if either of the values is true. For example, @v1 || Y has a value of Y (true) whatever the value of the variable v1.
The logical NOT operator '!': This inverts a single value, being true if the value is false, and vice versa. For example !@v1 is exactly equivalent to @v1 == "".
Boolean values can be used directly, when the Y or "" is appropriate, or in the alternation operator, described here, or by if statements, described below.
The alternation operator returns the value of one of two expressions, depending on the value of a boolean expression and takes the form:
@bool ? @vtrue : @vfalse
If '@bool' is true, the expression's value is that of '@vtrue', and if '@bool' is false, the value is that of '@vfalse'.
Operator Summary
In the table below, each operator is followed by its name and an example of its use.
 
Operator
Description
Example
!
Not
!@bool
+
Concatenate
"NMS:" + $E.outageHdl.idx
==
Equal
@v1 == @v2
!=
Not equal
@v4 != on
&&
Logical AND
@b1 && @b2
||
Logical inclusive OR
@b3 || @b4
? :
Alternation
@bool ? @vtrue : @vfalse
 
The not operator is right associative, all the others are left associative. For example, !!@v means !(!@v), and @v1 + @v2 + @v3 means (@v1 + @v2) + @v3, and @v1 == @v2 == @v3 means (@v1 == @v2) == @v3.
Each box holds operators with the same precedence. An operator has a higher precedence than those in lower boxes. For example, @v1 == @v2 + @v3 means @v1 == (@v2 + @v3).
Parentheses can be used to change the precedence. For example, (@v1 == @v2) + abc would result in "Yabc" if @v1 was the same as @v2, otherwise "abc", while @v1 == @v2 + abc would result in "Y" or "" depending on whether the value of v1 is the same as the value of v2 concatenated with "abc".
Parentheses should be used whenever the precedence is in doubt, especially when a boolean expression becomes more complex.
Input Elements and Attributes
The element statements described above in section 7.1 are used in Output Documents. Elements in Input Documents do not have values assigned to them, as the element values are supplied by the incoming XML. An example of an input element follows:
&JobNumber;
This defines an element whose tag is JobNumber. This element is optional; it does not have to be present in the input XML for the enclosing Input Document to be processed. In addition, no attributes were declared for the element; therefore, any attributes for the element in the input XML will be ignored.
When parsing the input, XML namespace prefixes are ignored; only the local name of a tag in the input XML is used to match the tag to an element in the enclosing Input Document. Consequently, in order to match, elements in Input Documents should not specify namespace prefixes.
If the element is not present in the input XML, its value is the element's default. The specification of default values is described below. In this example, the default is "", the empty string. If special processing should take place when an element is present or not, the boolean function 'isSet' can be used to alter the processing logic using, for example, an 'if' statement, described below.
The value of the element can be used in assignments, expressions, and in the various SQL statements. For example:
@jobNo = &JobNumber;
assigns the element's value to the variable 'jobNo'.
To declare that an element is required for the Input Document to be processed, the required flag 'R' would be added to the declaration, as described below in section Flags. An example of an element with four sub-elements is:
&CrewKey
{
&CrewName;
&AgencyCode;
&ShiftCode;
&ShiftDate;
}
The default way to obtain the value of a sub-element is to specify parent's tag, followed by a forward slash ('/'), followed by the sub-elements tag. Deeper nesting of elements is similar. For example:
@crewId = &CrewKey/CrewName + &CrewKey/AgencyCode + &CrewKey/ShiftCode + &CrewKey/ShiftDate;
If the nesting is very deep, it can become very tedious and error prone to have to type all the tags leading to a particular element. This can be avoided by giving the element a name, as described in section Alternate Names.
Input attributes are declared similarly to Output Document element attributes. For example:
&Elem < attr1; attr2; >;
declares an element with a tag of 'Elem', with two attributes 'attr1', and 'attr2'.
The value of an attribute can be obtained as follows:
@val = &Elem<attr2>;
The attribute name is enclosed in angle brackets '<' and '>'.
SQL Insert and Update Statements
SQL Insert and Update statements are used to save data to the database. For example, the statement:
sqlinsert picklist_completion_log |
ref_id, who, reason_for_update, when |
$O.event.idx, @crewId, @reason_for_update, time();
inserts a row into the 'picklist_completion_log' table. The value of the 'ref_id' column is supplied by the index of the Handle held in the 'event' field of the external object 'O' (Order), that is associated with a particular MDS Order. The value of the 'who' and 'reason_for_update' columns are supplied by the variables 'crewId' and 'reason_for_update'. The 'when' column is supplied by the 'time' function, which returns the current time in internal format.
The 'sqlinsert' introduces the SQL insert statement, and is followed by the table or view name, followed by a vertical bar (|) as a separator. The list of column names follows, separated by commas, and terminated by a vertical bar. The list of data sources follow, separated by commas, and terminated by the statement terminator, ';'. The number of sources must match the number of columns.
The table name or a data source can be a constant or the value of a variable, an element, an external data field, a function call, or the result of an expression.
If the table name is constant, the columns are checked for validity at initialization time. If any of the columns specified are not in the table, an error message is output to the log, and initialization fails.
If the table name is not constant, the columns are checked for validity at run time. If the table does not exist, nothing is sent to the database, and, optionally, a debug message is output to the log. If a column is missing, the data for the column is not sent to the database, and, optionally, a debug message output to the log.
The type and length of the columns are read from the database, the first time a table is accessed (commonly at initialization time). Values for character columns (CHAR or VARCHAR2) are truncated to the column length. Values for NUMBER and FLOAT columns are checked for validity, and invalid numbers are set to NULL. Values for DATE columns are assumed to be in the internal time format and are checked for validity and set to NULL if invalid. Invalid column values are output to the log file.
The SQL Update statement is for use in tables with a set of key columns. If there is a row with the keys set to the values used in the statement, that row is updated. If there is no row with the same keys, the row is inserted.
For example:
sqlupdate picklist_info_upd_tr |
system_om, type_om, crew_restore |
&System, &Type, @restoredTime |
ref_id | $O.event.idx;
ensures that there is a row in the 'picklist_info_upd_tr' table with a 'ref_id' column equal to the outage's event index, and sets the 'system_om', 'type_om', and 'crew_restore' columns to the values in the 'System' element, 'Type' element, and 'restoredTime' variable, respectively.
The 'sqlupdate' introduces the SQL update statement, and is followed by the table or view name, followed by a vertical bar (|) as a separator. The list of non-key column names follows, separated by commas, and terminated by a vertical bar. The list of non-key data sources follow, separated by commas, and terminated by a vertical bar. The number of non-key sources must match the number of non-key columns. The list of key column names follows, separated by commas, and terminated by a vertical bar. The list of key data sources follow, separated by commas, and terminated by the statement terminator, ';'. The number of key sources must match the number of key columns.
The set of rules for Update statements is the same as described above for Insert statements above, except that nothing is written to the database if a key column is missing.
If Statement
If statements are used to alter the flow of document processing, allowing elements to be generated optionally in output XML, different tables to be updated depending on data in incoming XML, etc. For example:
if (@doctype != create)
{
# there is no job number until the reply to the create document is received
&JobNumber = $O.externalId;
}
The statements between the brackets '{' and '}' are only processed when the variable 'doctype' does not contain the string "create".
An if statement can also have an 'else' clause. For example:
if (@v1 == @v2)
{
logDebug(0, "v1 is " , @v1, " as is v2");
}
else
{
logDebug(0, "v1 is ", @v1, " and v2 is ", @v2);
}
An if statement can have any number of 'elseif' clauses, optionally followed by an 'else' clause. For example:
if (@a == 1)
{
logDebug(0, "a is 1");
}
elseif (@a == 2)
{
logDebug(0, "a is 2");
}
else
{
logDebug(0, "a is ", @a, " neither 1 nor 2");
}
'else if' (two words) can be substituted for 'elseif'.
'if' statements can contain nested 'if' statements, for example:
 
if (@a == 1)
{
if (@b == 1)
{
logDebug(0, "a is 1, b is 1");
}
else
{
logDebug(0, "a is 1, b is ", @b);
}
}
elseif (@a == 2)
{
if (@b == 1)
{
logDebug(0, "a is 2, b is 1");
}
else
{
logDebug(0, "a is 2, b is ", @b);
}
}
else
{
logDebug(0, "a is ", @a, ", b is ", @b);
}
Flags
Flags are used to modify the behavior of elements, attributes and variables. Flags are set by adding a flag specification to the entity's definition. Individual flags have a flag character, used in flag specifications.
The flags are:
The 'send on change' flag 'S'. This flag only applies to elements, attributes and triggers in Output Documents. It is described below in sections Change Detection and Triggers.
The 'always include' flag 'I'. This flag only applies to elements and attributes in Output Documents. It is described below in section Change Detection.
The 'don't save' flag 'D'. This flag only applies to elements and attributes in Output Documents. It is described below in section Change Detection.
The 'ignore attribute changes' flag 'A'. This flag only applies to elements in Output Documents. It is described below in sections Change Detection.
The 'default to current' flag 'C'. This applies to elements, attributes and variables in Output Documents. Normally when the source of an assignment fails (due to the unavailability of an incident, for example) the element, attribute or variable is set to its default (described below). If this flag is on, the previous value is used instead. This only has effect when change detection (see below) is in effect.
The 'required' flag 'R'. This flag applies only to elements and attributes in Input Documents. If this flag is set, the element or attribute must be present in the input XML for the Input Document to process the XML. If an attribute is required, the element itself is implicitly required.
Flags are set by adding a flag specification after the name in an element, attribute or variable declaration. For example:
 
&Elem:CSI = $E.devAlias;
 
The flag specification is the ':' followed by one or more flag characters.
All elements and attributes have definitions. However, variables do not have to be. They are implicitly defined when they are assigned in an assignment statement and in a SQL select statement. Such implicit definitions cannot have flag specifications. An example of a variable definition with a flag specification is:
 
@var:C;
Defaults
There are cases when the values for an element, attribute or variable are not available. In this case the values are set to the entity's default.
Values are not available in the following cases:
When an optional element is not present in input XML.
When insufficient incidents are associated with an event.
When a table name is dynamically set, for example a device's facility table, and a column is referenced that the table does not contain.
When a sqlselect statement selects no rows.
A function call cannot generate a value, perhaps because it needs to use an external object that is not available. The specific situations are discussed in the function reference section of DML Function Calls.
If no default is specified, and the 'default to current' flag is not set, the default value for an entity is "", the empty string. The 'default to current' flag is discussed above in Flags.
A default is specified by adding a default specification to the entity's definition, after its (possibly empty) flag specification. For example:
 
&CallerName::None = $I.0.getCustomerName;
This normally sets the 'CallerName' element to the name of the first customer that called. If the event has no incidents, the element's value is set to 'None'. In this case the flag specification ':' is empty, and is followed by the default specification ':None'. If a change to the element 'CallerName' causes an update, the 'S' flag is included in the flag specification:
&CallerName:S:None = $I.0.getCustomerName;
This time the flag specification is ':S' and the default specification remains ':None'.
Alternate Names
Alternate names can be given to elements, attributes, and variables. Their usage depends on the type of Document the entities are in.
Input Documents
In Input Documents, only elements can have alternate names. They are used to give the elements names, which are easier to use when the element is a deeply nested sub-element. For example:
&Grandparent
{
&Parent
{
&son:::Jim<jattr1;>;
&daughter;
}
}
 
Declares an element 'Grandparent' with one sub-element 'Parent', which has, in turn, two sub-elements 'son' and 'daughter'. 'son' has a name of 'Jim'. The following example accesses the value of 'daughter':
 
@dval = &Grandparent/Parent/daughter;
while accessing the value of 'son' uses the shorter and less error prone:
@sval = &Jim;
To obtain the value of the attribute of 'son':
@sattr = &Jim:<jattr1>;
When an element has a name, the long form cannot be used.
Output Documents
In Output Documents elements, attributes, and variables can have alternate names. They have two usages:
To allow other documents to set their values, for example using the function 'setDocValue', which needs the alternate name.
An example of this is when an order contains the estimated time of restoration (ETR), which is initially supplied by the Oracle Utilities Network Management System services. Subsequently, the field crew, after assessing the situation in the field, decides that this time is inappropriate and sends a message back. This message causes input XML to be sent to the adapter, which will then be processed in an Input Document. The document contains an API call to set the ETR in Oracle Utilities Network Management System to this value.
The ETR value in Oracle Utilities Network Management System now matches the ETR value in the MDS. However, the Output Document holds the value of all elements of the order sent to the MDS, to prevent unnecessary updates, and, in this example, will hold the ETR previously sent to the MDS.
The consequence of this situation is that the next time the event associated with the order changes, the Output Document will be triggered and a change to the ETR will be detected, even if no other elements have changed. This will cause an unnecessary transmission of an order update to the MDS.
The solution to this defeating of the change detection mechanism is to call 'setDocValue' with the new value, and the name of the element that contains the estimated time of restoration. Similar situations can arise for attributes and variables.
To uniquely name elements so that their values can be saved to the database so that change detection can continue to be effective over a adapter shutdown/restart cycle. This is further discussed in section MDS_ORDER_VALUE.
The name is specified in an alternate name specification following the (possibly empty) flag specification, and (possibly empty) default specification. For example:
&ETR:S:"No ETR":etr = formatDateTime($E.estRestTime);
This defines an element with the 'S' flag set, with a default of 'No ETR', and an alternate name of 'etr' which is set to the formatted value of the current event's estimated time of restoration.
Change Detection
When MDS orders are updated due to changes in the event that is associated with the order, it is important to send only the elements that have changed. This is because of the limited bandwidth available to transmit data to and from field crews.
In addition, some elements that change may not be important enough to cause an update to occur, for example, the number of customer calls that are associated with the event.
Some elements that do not change may have to be sent every time that an update message is to be sent, for example the order identifier could be the key on the MDS.
Change detection only applies to Output Documents, and only to documents that update data previously sent to the MDS. To indicate that change detection applies, change detection only occurs when the trigger invoking the Output Document has the 'S' (send on change) flag set. The rest of this section assumes that change detection applies.
The default setting for an element is that it is only included in the output XML when it changes, and that a change to the element is not important enough to cause an update to be in effect. For example:
&NumCustCalls = $E.custCall;
An element that causes the update to be sent has the 'S' (send on change) flag set. For example:
&IntDev:S = $E.devAlias;
An element that is always sent when the update is to be sent has the 'I' (always include) flag set. For example:
&Create:I < confirm="Always"; >;
The 'S' and 'I' flags can be combined. This means that the element is always sent on an update, and that a change to it causes an update to be sent. For example:
&JobNumber:SI=$O.externalId;
Change detection applies to element attributes in the same way as elements.
If the element or any attributes is to be included in the output XML, the element and all of its attributes (including those that have not changed) are included in the output XML.
When an object with an associated document is created, a copy is made of the document, with all elements and attributes marked as changed, because they have not been sent to the MDS yet. If an element is not included in the initial transmission of the document (due to an if statement), it, and all its attributes, remains marked as changed. Normally, this is the correct behavior. However, if it has constant attributes, and may is set externally by a call to setDocValue to suppress sending the value, the element will no longer be marked as changed, but the attributes will remain marked as changed. This means that the first time that the element is processed (due to the condition in the if statement changing), it will be transmitted because the attributes are marked as changed, which is likely not the intention.
Using the 'ignore attribute changes' flag 'A', defeats the behavior. It can be combined with the 'S' and 'I' flags, if appropriate. For example:
if (($E.est_source == "O") || ($E.est_source == "C"))
{
WorkCodeUDF:SA::ert = formatDateTime($E.estRestTime);
}
If the element or any attributes is to be included in the output XML, the element and all of its attributes (including those that have not changed) are included in the output XML.
The values of the elements and attributes are held in memory while the adapter is executing. In order to preserve these values over a shutdown/restart cycle, they are stored in the database. By default, the adapter saves all elements and attributes that do not have constant values. However, some element and attribute values are always set during the execution of the Output Document, for example:
if (@docType == "create0x22)
{
@conf = Always;
}
else
{
@conf = Never;
}
&Confirm:I = @conf;
In this example, there is no need to save the value of the 'Confirm' element. To prevent saving its value, add the 'don't save' flag 'D' to the element's definition, for example:
&Confirm:ID = @conf;
The table used to save the values of the order document is described in section The Order Tables.
The External Objects
The external objects are:
The Event object, identified by 'E', holds the data from the event's latest 'SRSoutput' data. The names of the fields are the relevant fields in the Oracle Utilities Network Management System SRSoutput class. They are listed in DML Function Calls.
The Incident object, identified by 'I', holds the data from the event's customer calls. The Incident object is not automatically populated. It can be populated by a call to the function readIncidents(). If memory is at a premium, the Incident object can be unpopulated by the function clearIncidents(). The names of the fields are the relevant fields in the Oracle Utilities Network Management System Incident class. They are listed in DML Function Calls. There can be any number of incidents associated to an event, including zero. Therefore, the offset of the incident of interest has to be supplied when accessing an incident field. Offsets start at zero. The offset is an integer, and is the second component of the external data reference. For example, $I.1.getCustomerName reads the name of the second customer in the incident array. A function, sortIncidents(), is supplied to sort the incidents. Before sorting they are in the order that the customers called. Any reference to an incident field can fail, because there may be no incidents. Such a failure causes the value of the element, attribute or variable being assigned to be set to its default.
The Order object, identified by 'O', holds data relating to orders sent to the MDS. It holds the order's current event object (possibly aggregated to summarize a set of related events), the Output Document that holds all the document data for the order for change detection, a number of fields that are always available (section Permanent Order Object Fields, Permanent Order Object Fields of DML Function Calls), and other data fields as configured by the MDS_ORDER and MDS_ORDER_FIELD tables. See MDS_ORDER for a description of the order tables.
The Relationship object, identified by 'R', holds data relating to event relationships processed by the dml. It holds the type of relationship, the handles of all the related events, and a number of fields that are always available (see section Permanent Relationship Object Fields, Permanent Relationship Object Fields of DML Function Calls).
The Global Data object, identified by 'G', which holds named values for use by any of the documents. A field is created by assigning values to the field; for example, $G.QueueManager = OPS;. If a field that has not been created is read, the field is created with a value of "", the empty string, and an warning is output to the log. The global data object usually holds configuration data, and the fields are set in a Configuration Document.
The Trigger Parameter object, identified by 'T', which holds the parameters sent to Output Documents when they are triggered from another document using the function 'triggerOutputDoc'. The first parameter to 'triggerOutputDoc' specifies the Output Document to trigger, the second parameter specifies the trigger to pull, and the rest of the parameters values are available to the Output Document as fields '1', '2' … up to the number of parameters supplied, less two (the document and trigger names). For example, @param1 = $T.1; sets the variable 'param1' to the value of the first parameter.
Input Element Arrays
The declaration of input elements discussed in section Input Elements and Attributes . can only handle elements whose tags are unique within the bounding parent element (which may be the root element). If such an element appears in the input XML, its value (or those of its own sub-elements) will override the values previously read. Input element arrays solve this problem.
Generally there are two situations that repeated elements are required:
When the elements contain the same type of data and each should be processed in a similar fashion. For example, a crew logs on when the MDS had previously assigned multiple orders to the crew. Each of these assignments should be made to the crew on Oracle Utilities Network Management System.
When the elements contain different types of data, and the individual elements are identified by the value of a particular attribute, in effect giving the element a compound tag.
Using an element array with an unspecified index solves the first situation. For example:
&CrewAssignments
{
&CrewAssignment[]
{
&OrderId;
&AssignmentStatus;
}
}
This allows any number of elements with the tag 'CrewAssignment' to be processed. This can be achieved using the 'for' statement described below.
Using an element array with a specified index attribute solves the second situation. For example:
&UDFS
{
&UDF[idx];
}
 
@etr = &UDFS/UDF[et];
@troubleType = &UDFS/UDF[tt];
which assigns the 'UDF' element whose 'idx' attribute is 'et' to the variable 'etr' and the 'UDF' element whose 'idx' attribute is 'tt' to the variable 'troubleType'.
Array elements can be given alternate names in the same way as normal input elements, but they cannot be given flags and defaults, as they have no meaning. Individual array indices can be required to be present, using a required index specification. For example:
&UDFS
{
&UDF[idx] R(et, tt);
}
@etr = &UDFS/UDF[et];
@troubleType = &UDFS/UDF[tt];
Prevents the processing of the input XML when the input XML does not contain a 'UDF' element with an 'idx' attribute of 'et' and contain a 'UDF' element with an 'idx' attribute of 'tt'. The required index specification consists of an 'R' followed by a comma separated list of attribute values in parentheses '(' ')'.
While sub-elements to array elements can be given names, their usage differs from normal sub-elements because the appropriate index must be specified. This is done using a format similar to the long form of referencing tags, using forward slashes '/'. For example:
&ancestor
{
&grandparent[idx]
{
&parent
{
&child;
}
}
}
@son = &ancestor/grandparent[smith]/parent/child;
uses the full long form.
 
 
 
&ancestor
{
&grandparent[idx]:::granny
{
&parent
{
&child;
}
}
}
@son = &granny[smith]/parent/child;
 
uses a name for the array element.
 
&ancestor
{
&grandparent[idx]:::granny
{
&parent
{
&child:::son;
}
}
}
@son = granny[smith]/son;
uses a name for both the array element and its sub-element.
For Statement
The for statement, or for loop, is used to iterate through the contents of an array element.
The array element can either have a specified index attribute or an unspecified index. The usage is similar.
For example:
&CrewId:R;
 
&CrewAssignments
{
&CrewAssignment[]:::asn
{
&OrderId;
&AssignmentStatus;
}
}
if (!findCrewById(&CrewId))
{
stop;
}
 
for (&asn[], @i)
{
if (isSet(&asn[@i]/OrderId) &&
isSet(&asn[@i]/AssignmentStatus) &&
findOrder(externalId, (&asn[@i]/OrderId))
{
if (&asn[@i]/AssignmentStatus == ASN)
{
assignCrew();
}
elseif (&asn[@i]/AssignmentStatus == DSP)
{
dispatchCrew();
 
}
}
}
 
The for statement executes all the statements between the matching brackets '{' and '}', for each of the elements in the tag array ('&asn[]' in this case), in the order that they appeared in the input XML. During execution of the statements the 'for' variable ('@i' in this case) is set to the elements index in the tag array. As this array did not have an index attribute specified, the variable has a numeric value, starting at zero, and is incremented by one between loop executions. If the XML does not contain the element, the loop is never executed.
If, instead, the array element had an index attribute, for example:
&CrewAssignments
{
&CrewAssignment[idx]:::asn
{
&OrderId;
&AssignmentStatus;
}
}
 
the loop variable would contain the values for the 'idx' attribute included in the input XML. Note, however, that if the XML contained any 'CrewAssignment' elements, without an 'idx' attribute, these elements would be ignored, and therefore not available for processing.
Queue Specification
The queue specification is used to specify the queue that XML from Output Documents are sent to, and the queue that input XML is received on to be processed by Input Documents. The queue specification appears in the header portion of the document. For example:
 
queue = NMS.TO.MDS.REQUEST;
 
Which sets the queue name to a constant. Commonly, the queue is set to the value of a field in the global object to facilitate the configuration of the queue names.
Output Documents can change the queue name by accessing the queue variable in the body of the document. For example:
 
If (@use_alternate_queue)
{
@queue = $G.alternateQueue;
}
 
Association of an Output Document to the Order Object
The order document must have an associated Output Document that generates the Order creation (usually) and update (always) XML. It is used to cache all the element data that is used for change detection. This association is achieved using the associate specification in the document header which takes the form:
 
associate = O;
 
where the 'associate' is the associate keyword and the 'O' identifies the Order Object.
Triggers
Triggers specify when Output Documents are activated to generate XML to be sent to the MDS. For example:
 
trigCreateOrder < SRSoutput; > =
($E.status == "ACK") && !findOrder(event, $E.outageHdl);
 
might be used to trigger the creation of an order.
The 'trigCreateOrder' is the trigger's name. The value of a trigger is available to the body of the document in a variable with this name.
The angle brackets, '<' and '>', contain the trigger specification(s), which define the circumstances under which the trigger is to be tested. In this case the arrival of an asynchronous 'SRSoutput' message.
After the assignment is the expression which determines when the trigger is to be fired. The expression is evaluated, and, if it is true (not the empty string), the trigger is fired. The result of this evaluation is then assigned to the trigger variable. In the example, the trigger will fire if the event is in the acknowledged state and no order has been created for the event.
If an expression is not supplied, the trigger always fires when the trigger specification is satisfied. In this case, its value is set to 'Y'.
Triggers can also have the 'send on change' 'S' flag set. If not set, all elements in the document are sent in the resulting XML. If set, only those elements that have changed are set. For example:
 
trigUpdateOrder:S < SRSoutput; > =
(!isIn($E.status, "UNA", "CNL") && findOrder(event, $E.outageHdl);
 
There can be multiple triggers, only one of which is fired. The triggers are evaluated in order of their definitions and the first to fire takes effect. The unfired triggers all have a value of false.
There are a number of types of trigger specifications. In some cases they need values. They are:
The reception of a SRSoutput message. The trigger specification is 'SRSoutput', which has no value. Examples of the SRSoutput trigger are shown above.
When an event is deleted. This occurs when outages are merged, and when a previously processed event is not returned by JMService at start up. The trigger specification is 'EventNonexistent', which has no value. Commonly, this triggers the same Output Document that handles event cancellation. The event is supplied in trigger parameter 1. An example of an event non-existent trigger is:
triggerEventNonexistent<EventNonexistent;>
= findOrder(order, $T.1) && $O.externalId;
Periodically. The trigger specification is 'Periodic', which needs a value that is the period at which to fire the trigger, in seconds. An example of a periodic trigger that fires once a minute is:
trig1min< Periodic=60; >;
By request in another document, using the 'triggerOutputDoc' function. The trigger specification is 'OnRequest', which needs a value that is the number of trigger parameters that need to be passed by the requesting document. An example of a request trigger with two parameters is:
trigOnRequest<OnRequest=2;>
= findOrder(event, $T.1) &&
isIn($E.status, "UNA", "CNL") &&
$O.externalId;
Creation of, changes to the number of events in, and deletion of an event relationship processed by dml. The trigger specification is 'RelationChanged', which as no value. The Output Document is activated once for each event in the relationship. The event is supplied in trigger parameter 1. An example of an relationship change trigger is:
trigRelationChanged< RelationChanged; >
= findOrder(event, $T.1) &&
isIn($E.status, "UNA", "CNL");
Deletion of an event relation processed by dml. The trigger specification is 'RelationDeleted', which as no value. The Output Document is activated once for the relationship. The relation is supplied in trigger parameter 1. An example of an relationship deletion trigger is:
trigRelationDeleted< RelationDeleted; >
= findOrder(RELATED_OUTAGE, relation, $T.1) &&
$R.externalId;
A change to the number of events in an event relation that is aggregated by the adapter. The trigger specification is 'AggregateChanged', which has no value. The Output Document is activated once for the order in which the events are aggregated. The order is supplied in trigger parameter 1. An example of an aggregate change trigger is:
trigAggregateChanged< AggregateChanged; >
= findOrder(order, $T.1) &&
$O.externalId;
This trigger is often used to ensure that all events in the relation have data updates sent by the MDS before new events are added to the relationship, for example the estimated time to restore.
An SRSoutput message arrives indicating number of events are merged. The trigger specification is 'EventMerged'. Its value specifies the name of an Output Document, known as the Merge Priority Document, which is used to generate the priority of all of the orders associated with the events involved in the merge, if any. The Merge Priority Document must have a request trigger named 'call'. The Output Document that contains the event merged trigger is known as the Merge Document. There can be zero or one Merge Document in all the dml files processed by the adapter. If no Merge Document is supplied, the SRSoutput message is processed via SRSoutput triggers, and the merged events are processed via event non-existent triggers. If a Merge Document is supplied, the adapter processes the SRSoutput message as follows:
1. For each of the events involved in the merge, including the surviving event, the adapter determines whether the event is associated with an order. If so it's order becomes eligible to be the surviving order, except for a non-surviving event's order is in an aggregate relationship. If there are no eligible orders, the SRSoutput message is processed via SRSoutput triggers, and the merged events are processed via event non-existent triggers. Neither the Merge Document nor the Merge Priority Document is processed.
2. When there are multiple eligible orders, the adapter must choose which one will become the survivor. The Merge Priority Document provides a priority value to allow this choice to be made. The adapter processes the Merge Priority Document via the 'call' trigger. The Merge Priority Document has its order and event objects set. Note that if the event is the surviving event, the previous version of the event object is set. This allows the event object's fields before the merge to be used to determine the priority.
3. The Merge Priority Document returns the priority in the trigger argument object. The priority consists of a priority sort definition and one or more priority values. The priority sort definition is returned in the '0' (the character zero) field of the trigger argument object ($T.0). If this value is the empty string, the order is no longer eligible to survive. If not empty, it defines the number and sort order of the priority values. The priority values are returned the '1', '2', … fields ($T.1, $T.2, …), up to the number of values. The number of characters in the priority sort definition determines the number of values expected by the adapter. Each character determines the sort order for the corresponding value, 'A' or 'a' for ascending and 'B' or 'b' for descending, the first character applies to $T.1, the second to $T.2, etc.
4. If there are multiple orders eligible, the one with the highest priority becomes the survivor. Each priority value is sorted alphabetically in the order specified by its character in the priority sort definition. The first value ($T.1) is examined first. If one order ranks higher that all the other, it is chosen. Otherwise, any order with a lower priority is discarded. Then the other values are examined in turn, until an order is chosen. If all the priorities are the same, the order associated with the surviving event, if any, survives. If the surviving event has no order, the order associated with the oldest event survives. For example, the following dml fragment illustrates how to choose the order with the most advanced crew assignment/dispatch status, and if they are equal the order with the oldest event.
 
# two priority values, the first descending, the second ascending
$T.0 = DA;
 
# orderCrewStatus() returns 'A' for Assigned, 'D' for dispatched,
'O' for on site, nothing for none
@ocr = orderCrewStatus();
if (@ocr)
{
$T.1 = @ocr;
}
else
{
# 'a' precedes all of the valid values
$T.1 = a;
}
 
# formatDateTime() returns the date and time in the format
# YYYY-MM-DDTHH:MM:SS
$T.2 = formatDateTime($E.outageTime);
5. The Merge Priority Document can populate other fields in the trigger argument object, to be used by the Merge Document when the order being processed becomes the surviving order. Note that the Merge Priority Document is processed even if there is only one eligible order so that these fields, if any, can be passed to the Merge Document.
6. If the surviving order is not associated with the surviving event, the surviving order is re-associated to the surviving event. The order that was associated with the surviving event is re-associated to the surviving order's old event, so that it can be processed via an event non-existent trigger, to allow normal order clean up.
7. The adapter processes the Merge Document with the surviving order object and surviving event object set to the new version of the event, and the trigger argument object fields set by the Merge Priority Document when processing the surviving order.
8. Finally, the SRSoutput message is processed via SRSoutput triggers, and the merged events are processed via event non-existent triggers.
An example of an event merged trigger is:
TrigEventMerged <EventMerged="OrderMergePriority";>;
For this to be valid, there must be an Output Document named 'OrderMergePriority', with a request trigger named 'call'.
The Root Element
The root element is the element that contains all of the other elements in an XML document. The root element in dml serves a different purpose depending on whether it is part of an Output or Input Document.
In an Output Document, it is used to generate the root element in the XML to be sent. In an Input Document it is used to select the Input Document or Documents that the input XML can be processed by, similar to a trigger for an Output Document. An example of a root element follows:
&RootElement <environment = $G.environment; revision = "1.0.0";> = CreateJob;
The root element has the same format for both Input and Output Documents.
The root element differs from other elements in that the element's tag is defined by the value of the element, 'CreateJob' in this example. The pseudo-tag 'RootElement' keyword identifies it to be the root element.
In an Output Document, the example would generate the following start element tag:
<CreateJob environment="Test" revision="1.0.0">
assuming that the global field 'environment' held the value 'Test'.
To select an Input Document, the input XML's root element must have the same tag, and all the attributes in the root element specification must be present and have exactly the same contents. Extra attributes in the XML's root element are ignored.
An Input Document with the same root element definition example above would be selected by the root element in the example above.
The root element is defined in different areas, depending on the type of document.
In an Output Document the root element is in the body of the document, because it's tag may have to be determined during document processing. It is the only element in an Output Document that is an exception to the rule that states that elements are generated in the order that they appear in the Output Document.
In an Input Document the root element is the header of the document because it is used before any processing is done in the document.
The Base Path
The base path only applies to Input Documents, and is not necessary, but can make Input Documents more compact. Consider the following XML:
<ConfirmJob>
<ApplicationArea>
</ApplicationArea>
<DataArea>
<Job>
<OriginalApplicationArea>
<BODId>OrigBODId</BODId>
</OriginalApplicationArea>
<CreateSuccess>
<JobNumber>1234567890</JobNumber>
</CreateSuccess>
</Job>
</DataArea>
</ConfirmJob>
The XML could contain many other elements, but the 'BODId' and 'JobNumber' are the only elements to be processed. The elements in the Input Document would be:
&DataArea
{
&Job
{
&OriginalApplicationArea
{
&BODId;
}
&CreateSuccess
{
&JobNumber;
}
}
}
Note that 'BODId' and 'JobNumber' have a common grandparent 'Job'. By setting the base element to the grandparent by adding:
BasePath = DataArea/Job;
to the document's header, the elements would become:
&OriginalApplicationArea
{
&BODId;
}
&CreateSuccess
{
&JobNumber;
}
Stop Statement
The Stop statement causes the processing of the current document to stop. It takes the form:
stop;
It is usually contained in an 'if' statement. Any statements with side effects, for example a SQL Insert, processed before the 'stop' do take effect.
A stop statement prevents an Output Document's XML from being sent.
A stop statement in a Configuration Document, described below, causes initialization to fail.
Include Statement
Sometimes it's useful to have the same set of statements in two different places in a dml file. For example all Output Documents may need the same header, or application area. This can be achieved by placing the repeated statements in another file and then including the file more than once in another file. The following is an 'include' statement:
include ohdr.dml
This 'include' statement in effect replaces the text 'include ohdr.dml' with the contents of the file 'ohdr.dml'. Files being included can also include other files, but the nesting level is limited to 10 deep so that infinite recursion can be prevented.
Configuration Documents
Configuration Documents are used to set configuration data and load configuration tables from the database at initialization time. They are similar to Input Documents, but have no elements.
They are processed at initialization time, and are then discarded. Any errors encountered when processing a Configuration Document should be made fatal by executing a stop statement, causing initialization to fail.
Common uses are to set fields in the global data object, including configuration fields, and to load mapping tables, used by the 'mapTableStr' and 'mapTableCode' functions described in DML Function Calls. For example:
ConfigDoc Configure
{
# fields for other documents
$G.OutRequestQueue=NMS.MDS.REQUEST;
$G.OutErrorQueue=NMS.ERROR;
$G.InReplyQueue=MDS.NMS.REPLY;
$G.InRequestQueue=MDS.NMS.REQUEST;
$G.environment=Test;
 
# configuration parameters
$G.config_QueueManager_name=OPS;
$G.config_OutQueue_req_name=$G.OutRequestQueue;
$G.config_OutQueue_err_name=$G.OutErrorQueue;
$G.config_OutQueue_numThread=5;
$G.config_InQueue_rep_name=$G_InReplyQueue;
$G.config_InQueue_rep_numThread=2;
$G.config_InQueue_req_name=$G.InRequestQueue;
$G.config_InQueue_req_numThread=4;
$G.config_ErrorQueue_name=$G.OutErrorQueue;
$G.config_ErrorDoc_name=Error;
$G.config_ErrorDoc_trigger=xmlErrorTrigger;
 
$G.config_Relation_Aggregate_AcknowledgeEvents = ack;
$G.config_Relation_Aggregate_type = PARTIAL_RESTORATION;
$G.config_Relation_Aggregate_ActiveEvents = Y;
$G.config_Relation_dml_type = RELATED_OUTAGE;
 
 
# Load map tables
if (!loadMapConfigTable(mds_map_config) ||
!loadMapTable(mds_cls_desc) ||
!loadMapTable(mds_cls_type))
{
stop;
}
}
Configuration Fields
Configuration fields have names starting with 'config_'. The available configuration fields are:
config_QueueManager_name: The name of the queue manager to use. This field must be specified, or the adapter will exit with a configuration error message.
config_OutQueue_<id>_name: The name of an output queue to use. Each output queue needs to have a unique id, which replaces the '<id>'. The unique id may not contain an underscore (_).
config_OutQueue_numThread: The number of threads to use to generate output documents. If not specified, one thread is used to generate output documents.
config_InQueue_<id>_name: The name of an input queue to use. Each input queue needs to have a unique id, which replaces the '<id>'. The unique id may not contain an underscore (_).
config_InQueue_<id>_numThread: The number of threads to use to process input documents arriving on the input queue with the same id. Each input queue needs to have a unique id, which replaces the '<id>'. If not specified, one thread is used to process documents on the queue.
config_ErrorQueue_name: The name of the queue to send XML parse error and warning reports to. This field must be specified, or the adapter will exit with a configuration error message.
config_ErrorDoc_name: Specify an output document to process error reports. If specified, the config_ErrorDoc_trigger field must be specified. If not specified, the standard XML error document, as specified in the MQ/XML adapter documentation, is used.
config_ErrorDoc_trigger: The trigger to pull in the error document when there is an error or warning to report. Ignored is no error document is specified. If the specified trigger does not exist in the error document, the adapter exits with a configuration error message. The adapter supplies three trigger arguments to the error document. Argument one is the error or warning message description, argument two is the priority level, one of 'Warning', 'Error', and 'Fatal Error', and argument three is the offending XML document.
config_Relation_Aggregate_type: A comma separated list of relationship types to aggregate. The relationship types are: NESTED_OUTAGE, MOMENTARY_OUTAGE, PARTIAL_RESTORATION, and RELATED_OUTAGE. If a pseudo relationship of a type that is aggregated by the adapter is created using createPseudoRelation(), the pseudo relation is aggregated. If a relationship type is configured for both aggregation and dml processing, the adapter exits with a configuration error.
config_Relation_Aggregate_AcknowledgeEvents: Acknowledge all unacknowledged events in aggregate relations. The value of this field is used in a call to JMS::requestRowAction() as the button name. This field should be set if pseudo aggregate relations are created on events that may not be acknowledged.
config_Relation_Aggregate_ActiveEvents: If the field is not the empty string "", sum count data for all active events in an aggregated relation. The count data event fields are: customersOut, crit_k, crit_c, and crit_d.
config_Relation_dml_type: A comma separated list of relationship types to be processed by the dml, using the relationship object. The relationship types are: NESTED_OUTAGE, MOMENTARY_OUTAGE, PARTIAL_RESTORATION, and RELATED_OUTAGE. If a pseudo relationship of a type that is processed by the dml is created using createPseudoRelation(), the pseudo relation is processed by the dml. If a relationship type is configured for both aggregation and dml processing, the adapter exits with a configuration error.
config_Relation_dml_AcknowledgeEvents: Acknowledge all unacknowledged events in dml processed relations. The value of this field is used in a call to JMS::requestRowAction() as the button name.
config_MaxBackoutCount: The adapter uses the MQSeries syncpoint facilities to preserve input messages when there is a failure. Using the MQSeries syncpoint facilities introduces the possibility that a 'poison' message will be sent by the MDS. A 'poison' message is one that can never be successfully processed, for example because an Oracle Utilities Network Management System table has a constraint that the contents of the message violate. If the 'poison' message is never discarded, MDS will continually try to process the message, fail, and then restart. This parameter sets a limit on the number of restarts that MDS will perform before discarding a message. The default value is five. A value of zero disables this feature. If a message is discarded, the error is logged to the log file, including the offending XML, and if the error document is configured, and an error report is sent to the error queue.
config_Event_QueueDelay: When event data is received in an SRSoutput message, from JMService, they are held for this period before they are queued for processing. If another message for the same event is received before the delay has expired, the older message is discarded, and the new message is held for the delay period. This avoids unnecessary processing and message transmission when event data is changing rapidly. Setting this delay too short can cause extra messages, while setting it too long can cause poor response. The value is in seconds. The default value is four seconds. A value of zero disables this feature.
config_Event_ReprocessPeriod: In certain circumstances, for example when more that one event is grouped, the adapter needs to request an event's status from JMService. The adapter periodically requests these events' statuses in a single request, reducing the burden on JMService. In addition, if an SRSoutput message for one of these events arrives before it is time to do the request, the request does not have to be made. Setting this period too short can cause extra messages, while setting it too long can cause poor response. The value is in seconds. The default value is six seconds. The minimum value is two seconds. It must be at least 2 seconds longer than config_Event_QueueDelay.
config_Crew_AssignmentCheckPeriod: When the assignment of crews to events is the responsibility of the adapter, as a proxy for the MDS, Oracle Utilities Network Management System can be configured to reduce the possibility of an operator inadvertently assigning a crew to an event. However, it must be possible to assign crews if Oracle Utilities Network Management System cannot communicate with the MDS, hence mistakes can happen. The adapter periodically checks all crew assignments. A sub-set of crew assignments is checked at the end of each period, the events in ten orders, and ten crews for events not in an order being checked each time. Setting the period too short causes unneeded processing, setting it too long delays such mistakes being repaired. The value is in seconds. The default value is six seconds. A value of zero disables this feature.
config_Crew_MoveAssignmentCheckDelay: When crew assignments are being checked, allowing the checking to occur during event grouping can, in some configurations, cause unnecessary message traffic between the adapter and JMService. To prevent this, when a grouping happens, crew assignment checking is delayed. The value is in seconds. The default value is two seconds. A value of zero disables this feature.
config_Relation_CheckPeriod: When event relationships are processed by the adapter, the adapter loads the relationship database table each time a relationship is created, changed or deleted. In addition, the adapter checks for changes to the table at this period. The value is in seconds. The default value is 30 seconds. A value of zero disables this feature.
config_IgnoreCondStatus: In most implementations of the adapter, additional alarms in the Oracle Utilities Network Management System Work Agenda should not be processed. The value of this configuration parameter is a list of condition statuses, separated by commas (,), that are to be ignored by the adapter. To ignore additional alarms (often NFY events) set this value to 12.
config_CompleteStatus: In certain situations the adapter need to be able to determine if an event is complete, for example to prevent the assignment of a crew to a completed event, which is illegal. This can only be determined by examining the status string for the event, which is configurable in Oracle Utilities Network Management System. The value of this configuration parameter is a list of statuses, separated by commas (,), that indicate that an event is complete. The default value of this parameter is CMP, CNL.
config_EventUpdateTimeout: When device outages are confirmed and restored (using confirmDeviceOutage() and restoreOutage()), the new state of the event(s) needs to be read from JMService. Because device operations are initiated by a message to DDService, which sends a notification to MTService to update the model, which subsequently notifies JMService of the model change, the new state cannot be read immediately, because JMService may not have received the notification. To avoid this, the adapter waits for an SRSoutput message updating the event before reading the new state. To prevent the adapter from hanging if an event update does not occur, a timeout is used to interrupt the wait. This value is the timeout in seconds. The default value is 20 seconds. The minimum is two seconds.
config_MaxThreadBusyUntilFatalError: The adapter monitors the input and output threads to detect Mutex deadlocks, which would cause the adapter to hang. This value is the maximum number of seconds that a thread can be responding to a single trigger or input XML document. The default value is 300 seconds (5 minutes). The minimum is 60 seconds.
config_StopServiceOnHighLevelStop: The adapter runs as a Windows Service, and it usually set to restart after a period after it fails. (This period is often the minimum one minute). If the adapter tells Windows that it has stopped normally, using a Service Stop message, just before exiting Windows does not try to restart the adapter. If the adapter does not send a Service Stop message, Windows will restart the adapter. When the adapter exits due to Stop request from the Service Property dialog, it sends Windows a Service Stop message, because the user is intending that the adapter stops and does not restart. When the adapter exits abnormally, it does not send a Service Stop message so that Windows will restart the adapter. However, when the adapter is sent a high-level stop message from Oracle Utilities Network Management System using the Action command, the user may or may not want the adapter to restart. This value determines whether the adapter sends a Service Stop message under these circumstances. A value of 'Y' causes the adapter to send a Service Stop message, while a value of 'N' prevents the adapter from sending a Service Stop message. The default value is 'N'.
config_AllowCloseOutEventCancel: When this parameter is set to 'Y,' the DML function closeOutEvent will cancel the event instead of completing it, if the appliedRule value OUTAGE_PND_COMPLETE (26) is passed to the function. When this parameter is set to 'N,' the DML function closeOutEvent will not cancel events. The default value is 'Y'.
config_IgnoreStormmanUpdates: When this parameter is to set to 'Y' (default), the adapter will not process TRBL_ERT_UPDATE messages generated when Storm Management recalculates ERTs. When this parameter is to set to 'N' the adapter will process such messages.
config_AllowManualEntryForSCADA: When this parameter is to set to 'Y,' the adapter will perform manual entry in order to operate SCADA device in the NMS model. When this parameter is to set to 'N' (default), the adapter will not be able to operate SCADA devices.
config_Username: Username under which the adapter will perform crew-related API calls into NMS. Default value is 'MDS'.
config_UseGlobalUsernameForCrewOps: If set to 'Y,' then the value specified by the '$G.config_Username' will be used as the username under which the adapter will perform crew-related API calls to NMS. This is the default setting.
If set to 'N,' then the adapter will use the username provided in the DML function call. If a particular crew-related DML function does not accept username parameter or if the supplied parameter is empty the '$G.config_Username' value will be used.
config_BlockingMqGetEnable: (boolean) If true, the blocking get() behavior will be enabled. Default is false.
config_BlockingMqGetWaitInterval: (integer) The number of milliseconds that the adapter will wait for a message to appear on the queue before the MQGET call completes with the MQRC_NO_MSG_AVAILABLE reason code. This option only takes effect if config_BlockingMqGetEnable is "true0x22. Default is 2000 ms.
Pseudo Relationships
Pseudo relationships can be created by the dml so that all the events on a single device can be processed in the same way as an Oracle Utilities Network Management System created event relationship. The processing of these relationships is configured in a configuration document.
For example, a probable device outage is created from multiple customer calls grouping to the common transformer, but the crew discovers that there are multiple service problems only affecting some of the customers (perhaps a tree limb took down two service wires). The crew will fix all of the problems, so they do not need multiple MDS orders. When the individual service status is set for the affected customers, all the events generated will be treated in the same way as a partial restoration. (This example assumes that partial restorations are aggregated, and the dml creates a pseudo partial relationship when this situation arises.)
When all of the events in a pseudo relation are completed, the relation itself is automatically completed.
Configuration Tables
The following tables are used in conjunction with the dml files to configure the MDS adapter. They are loaded at startup, or, in some cases, when a dml statement needs them.
The Order Tables
The order tables save order data and configure the fields that are available to the dml in the external Order object, identified by 'O' in the dml.
MDS_ORDER
The MDS_ORDER table is used to save order data so that the adapter can continue to process orders over a adapter shutdown restart cycle. While not strictly a configuration table, it is described here to clarify the use of other configuration tables. The table has a fixed set of columns that are always in the table, and columns to hold Order object field values, element values and attribute values. The fixed set of columns is:
Column
Type
Description
h_cls
NUMBER
Order class
h_idx
NUMBER
Order Index
event_cls
NUMBER
Key event class
event_idx
NUMBER
Key event index
active_event_cls
NUMBER
Event class for last active event
active_event_idx
NUMBER
Event index for last active event
active
CHAR(1)
Active flag (Y = active, N = inactive)
when_xml_saved
DATE
When the XML data last sent to the MDS was saved in the database (in the UTC time zone).
when_created
DATE
When the order was created (in the UTC time zone).
when_completed
DATE
When the order was completed or canceled (in the UTC time zone).
comp_reason
VARCHAR2(64)
Text explaining why the order was completed or canceled.
The 'h_cls' and 'h_idx' columns make up the order handle, which identifies the order internally and are the key columns of the table. The order handle is available to the dml with a field name of 'order'. The 'event_cls' and 'event_idx' columns make up the handle of the key event for the order. If the event is not aggregated, this is the single event associated with the order. If the event is aggregated, this is the key event of the relationship that makes up the aggregate. The event handle is available to the dml with a field name of 'event'. The 'active' flag indicates whether the order is active (it has been created), but has neither been completed or canceled. 'when_created' holds the time and date the order was created. 'when_completed' holds the time and date the order was completed or canceled. comp_reason hold the text explaining why the order was completed or canceled. This text is supplied by the dml when it completes the order by calling the 'orderComplete' function.
The columns that hold the field, element and attribute values can have any name, but they must match the contents of the MDS_ORDER_FIELD table and MDS_ORDER_VALUE table. Both are described below. It is suggested that the columns be named similarly to the name of the entity, allowing for the requirements of column names (case insensitivity, etc.). The column types should be VARCHAR2. The columns should be wide enough to hold the data that will be stored in them. The off-line program that allows dml files to be checked before use can generate suggested contents for the MDS_ORDER, MDS_ORDER_FIELD, and MDS_ORDER_VALUE tables.
MDS_ORDER_FIELD
The MDS_ORDER_FIELD table maps the names of the fields in the Order object to the columns used to save their values in the MDS_ORDER table. In addition, it defines the names of all the fields that are available in the Order object. If the dml references a field that is not in this table, the adapter will log an error and initialization fails. The columns in the table are:
 
Column
Type
Description
name
VARCHAR2(32)
The field's name.
col
VARCHAR2(32)
The column in the MDS_ORDER table that holds the field's value.
MDS_ORDER_VALUE
The MDS_ORDER_VALUE table maps the names of the elements and attributes in the order XML to the columns used to save their values in the MDS_ORDER table. All elements and attributes except those with constant values, and those with the 'don't save' flag set, must be included in this map. The use of the 'don't save' flag is described in section Change Detection. The columns in the table are:
 
Column
Type
Description
name
VARCHAR2(32)
The element's or attribute's name.
col
VARCHAR2(32)
The column in the MDS_ORDER table that holds the element's or attribute's value.
The recommended way of naming the elements and attributes is to use the alternate name described in Alternate Names. If an alternate name is not specified, the adapter generates element names by numbering all the elements in the order that they appear in the Output Document and appending this number to the letter 'e', for example e1, e2. Note that all elements to be saved from the document are counted, including those with an alternate name, so that if a name is given to an unnamed element, all the other unnamed elements have the same name. If an attribute has no alternate name, the adapter generates the name by appending the underscore character '_' and the attribute's name to the attribute's element name, for example 'el_attr' is the name of the 'attr' attribute of an element with the alternate name 'el'.
Example
To illustrate the configuration of the order tables and example tables are shown below, based on the contents of the Output Document in DML Examples.
The MDS_ORDER table schema:
Column
Type
h_cls
NUMBER
h_idx
NUMBER
event_cls
NUMBER
event_idx
NUMBER
active
CHAR(1)
when_xml_saved
DATE
when_created
DATE
when_completed
DATE
comp_reason
VARCHAR2(64)
BODID
VARCHAR2(128)
E1
VARCHAR2(64)
E2
VARCHAR2(64)
E3
VARCHAR2(64)
E4
VARCHAR2(64)
E5
VARCHAR2(64)
E6
VARCHAR2(64)
E7
VARCHAR2(64)
E8
VARCHAR2(64)
E9
VARCHAR2(100)
E10
VARCHAR2(64)
E11
VARCHAR2(64)
E12
VARCHAR2(64)
E13
VARCHAR2(64)
E14
VARCHAR2(64)
E15
VARCHAR2(64)
E16
VARCHAR2(100)
E17
VARCHAR2(64)
E18
VARCHAR2(32)
E19
VARCHAR2(32)
 
The contents of the MDS_ORDER_FIELD table:
 
col
name
BODID
BODId
 
The contents of the MDS_ORDER_VALUE table (the element tag is not in the table, it is included here to illustrate the numbering of the elements):
col
name
Element tag
E1
e1
Component
E2
e2
Confirmation
E3
e3
AuthorizationId
E4
e4
CreationDateTime
E5
e5
BODId
E6
e6
ExternalNumber
E7
e7
CreationDateTime
E8
e8
Device
E9
e9
Address
E10
e10
DevPhases
E11
e11
FuseSize
E12
e12
WinterLoad
E13
e13
SummerLoad
E14
e14
NumCustOut
E15
e15
CallerName
E16
e16
CallerAddr
E17
e17
CallerPhone
E18
e18
CallerClues
E19
e19
CallerDevice
 
The Relationship Tables
The relationship tables save event relationship data and configure the fields that are available to the dml in the external Relationship object, identified by 'R' in the dml.
MDS_RELATION
The MDS_RELATION table is used to save relationship data so that the adapter can continue to process event relationships, and to detect changes in these relationships over a adapter shutdown restart cycle. While not strictly a configuration table, it is described here to clarify the use of other configuration tables. The table has a fixed set of columns that are always in the table, and columns to hold Relationship object field values. The fixed set of columns is:
Column
Type
Description
h_cls
NUMBER
Relation class
h_idx
NUMBER
Relation Index
key_event_cls
NUMBER
Class of key event
key_event_idx
NUMBER
Index of key event
pseudo_dev_cls
NUMBER
Class of pseudo device
pseudo_dev_idx
NUMBER
Index of pseudo device
type
NUMBER
The type of relationship one of:
NESTED_OUTAGE(1) MOMENTARY_OUTAGE(2) PARTIAL_RESTORATION(4) RELATED_OUTAGE(8)
Pseudo relationships have the same number as their type, with the sign bit (bit 31) set.
active
CHAR(1)
Active flag (Y = active, N = inactive)
when_created
DATE
When the relationship was created
when_completed
DATE
When the relationship was completed or cancelled
 
The columns that hold the field values can have any name, but they must match the contents of the MDS_RELATION_FIELD table, which is described below. It is suggested that the columns be named similarly to the name of the entity, allowing for the requirements of column names (case insensitivity, etc.). The column types should be VARCHAR2. The columns should be wide enough to hold the data that will be stored in them.
The off-line program that allows dml files to be checked before use can generate suggested contents for the MDS_RELATION and MDS_RELATION_FIELD tables.
MDS_RELATION_EVENT
The MDS_RELATION_EVENT table holds the events that are related to the key events in the MDS_RELATION table. It is not a configuration table. Its columns are:
 
Column
Type
Description
key_event_cls
NUMBER
Class of key event
key_event_idx
NUMBER
Index of key event
event_cls
NUMBER
Class of related event
event_idx
NUMBER
Index of related event
active
CHAR(1)
Active flag (Y = active, N = inactive)
MDS_ RELATION_FIELD
The MDS_RELATION_FIELD table maps the names of the fields in the Relationship object to the columns used to save their values in the MDS_RELATION table. In addition, it defines the names of all the fields that are available in the Relationship object. If the dml references a field that is not in this table, the adapter will log an error and initialization fails. The columns in the table are:
 
Column
Type
Description
name
VARCHAR2(32)
The field's name.
col
VARCHAR2(32)
The column in the MDS_RELATION table that holds the field's value.
The Code Mapping Tables
The code mapping tables and views are used to translate values in Oracle Utilities Network Management System to and from the equivalent values in the messages to and from the MDS. Typical usages include converting Oracle Utilities Network Management System control zones into dispatch areas on the MDS, and encoding long values in Oracle Utilities Network Management System to shorted encoded values. The dml uses these tables by calling 'mapTableStr' to convert from the MDS value to the Oracle Utilities Network Management System value, and 'mapTableCode' to convert from the Oracle Utilities Network Management System value to the MDS value. A table can be loaded using the function 'loadMapTable'. All these functions take the name of the table as a parameter.
The tables and views have the following columns:
Column
Type
Description
string
VARCHAR2
The value in Oracle Utilities Network Management System.
code
VARCHAR2
The equivalent value in message.
 
The width of the columns can be any appropriate value.
There are three types of mapping table:
Those that map from string to code. In these cases the strings must be unique in the table.
Those that map from code to string. In these cases the code must be unique in the table.
Those that map both ways. In these cases the strings and codes must be unique.
This can be configured in a map configuration table, described below. If these is no configuration for the table, and informational message is output to the log, and the table is assumed to map both ways.
It is sometimes convenient to add a code column to other Oracle Utilities Network Management System tables to avoid redundant data. Data from these tables can be accessed by use of a view that maps the appropriate column names to 'string' and 'code'.
If a value to be translated is not present in the table, a default value is used. If the default is not specified, the empty string is used.
The types of the tables and their defaults are specified in a map configuration table, which has the following columns:
Column
Type
Description
tablename
VARCHAR2
The name of the table the default applies to.
type
CHAR(1)
The type of the table. 'C' maps from string to code, 'S' maps from code to string, and 'B' maps both ways.
string
VARCHAR2
The default Oracle Utilities Network Management System value.
code
VARCHAR2
The default message value.
The width of the columns can be any appropriate value. A map configuration table is loaded using a function call similar to 'loadMapConfigTable(mds_map_config)'. The configuration document is a convenient place to do this. There can be multiple map configuration tables loaded.
The SRS Message Type Table
The SRS Message Type Table, MDS_SRS_MSG_TYPE, configures the processing of SRSoutput InterSys messages. It has the following columns:
Column
Type
Description
message_type
NUMBER
The SRSoutput message type that this row configures
action
CHAR(1)
How to process it. 'I', 'D', 'P' or 'R'.
proc_relation
CHAR(1)
Should special relationship processing be applied to it? 'Y' or 'N'.
special
CHAR(1)
Should special processing be applied to it? 'Y' or 'N'.
event_cls1
NUMBER
Event class for TRBL_ERT_UPDATE
event_cls2
NUMBER
Event class for TRBL_ERT_UPDATE
 
The message_type column values are the SRSoutput message types listed in SRSoutput.h.
The action column must be one of these values:
'I': completely ignore this message type. Any message type not included in the table is ignored.
'D': do not process the message, but apply the proc_relation and special flags if they are set.
'P': process the message as is, after applying the flags.
'R': reprocess the message's event after applying the flags. Some SRSoutput messages do not hold all of the event's data (e.g., DAMAGE_RPT_UPDATE), and some are used to update the viewer when conditions are to be hidden and may or may not indicate that an event has changed state (e.g., TRBL_REMOVE_ALL). As a consequence, these messages do not hold all the data required to process them. In these cases, the adapter requests JMService to send all the current data for the message's event.
When set to a value of 'Y', the proc_relation flag instructs the adapter to apply special relation processing to the message. This processing is activated when the appliedRule field of the SRSoutput message contains one of the following values: OUTAGE_PART_REST, OUTAGE_RELATED or OUTAGE_UNRELATED. These indicate that the event is part of a relationship that has been created, deleted or modified. In these cases, the adapter loads the current state of all relationships, reacts to the changes, and reprocesses the message's event after a delay to allow any upcoming changes to the event to arrive before rereading the event's data.
When set to a value of 'Y', the special flag instructs the adapter to apply special, message type specific, processing to the message. The following message types have special processing available:
TRBL_CLEAR: If the applied rule is not OUTAGE_MERGED, the event is processed by all Output Documents with a 'EventNonexistent trigger.
In addition to the processing of the special flag described above, the following message types are processed differently from normal SRSoutput messages because they are not formatted in the normal manner:
TRBL_ERT_UPDATE: This message contains a list of estimated time of restoration updates. If this message type is not completely ignored, all the events in the message are reprocessed. As this message contains the events' indexes, but not the events' classes, the potential classes need to be supplied in the event_cls1 and event_cls2 columns. One or both of the classes (normal and momentary event classes) can be configured. If one is zero, it is ignored.
TRBL_WCB_UPDATE: This message type is not implemented in the adapter. If this message is not configured to be completely ignored, the adapter issues a warning to the log each time this message type is received.
The High Priority Category Table
The High Priority Category Table, MDS_HIGH_PRI_CAT, configures the priorities used by the functions 'highPriTCCategoriesFromClues'. It has the following columns:
Column
Type
Description
group_order
NUMBER
A numeric representation of the trouble code categories
code
VARCHAR2(32)
The trouble codes for each trouble code category
priority
NUMBER
The priority of the trouble codes.
 
Note: The smaller the number the higher the priority. The higher the number the lower the priority
 
This table assigns the priority of each trouble code within each trouble code category.
Run Time Errors
There are many configuration errors that can be detected at initialization time, causing the adapter to exit. However, some configuration and other errors can only be detected at run-time.
All errors and diagnostic messages are output to the adapter's log file. Important messages are output to the Windows Application Event log. Important errors can be output in XML formatted to an error queue, if an Error Output Document is configured in a Configuration Document. Note that, under some circumstances, it may be impossible to output errors to one or more of these destinations.
The types of run-time errors, and the adapter's reaction to them are:
Data errors: These errors occur when badly formatted data is received. The input message is discarded.
Errors detected by the dml: The dml performs appropriate logic. Errors can be logged using the logging functions. Error XML can be sent by triggering the appropriate Output Document.
dml function call errors: These errors occur when a dml function is called and the prerequisites of the function are not met. The prerequisites of the functions are documented in DML Function Calls. This is regarded as a configuration error, causing the adapter to exit.
Mapping table errors: These errors occur when a map table function is called and the table name supplied by the dml does not exist in the database. This is regarded as a configuration error, causing the adapter to exit.
Errors when writing to the database: These are initially assumed to be transient, as some tables have constraints that contain time stamps. The adapter pauses for 1 second and re-tries. The adapter will retry 3 times. If all 3 re-tries fail, the adapter exits, on the assumption that there is a severe system problem. If the error occurred while an input message was being processed, and syncpoint is active (configured using the config_MaxBackoutCount field), the message will be re-processed after the adapter restarts. If this cycle is repeated too many times, the message is discarded.
API call failure: These are treated in the same way as errors writing to the database.
DML Examples
An Output Document
The following is an example of an Output Document that generates a create request document for a small MDS order. Various lines are numbered to allow reference to them in the explanation below. The numbers are not part of the syntax.
1 OutputDoc Job
2 queue=$G.OutRequestQueue; associate=O; persist="Y";
3 triggerCreate< SRSoutput; > = isIn($E.status, "ACK", "ASN", "ENR", "RST") &&
($E.outageHdl.cls != $G.momentary) &&
!findOrder(event, $E.outageHdl);
4 triggerUpdate:S < SRSoutput; > = findOrder(event, $E.outageHdl) &&
(!isIn($E.status, "UNA", "CNL"));
5 {
6 @docType = ChangeJob;
7 if (triggerCreate)
8 {
9 @docType = CreateJob;
10 createOrder();
11 }
12 &RootElement<environment = $G.environment; revision = "1.0.0";> = @docType;
13 &ApplicationArea
14 {
15 &Sender
16 {
17 &Component = NMS;
18 &Confirmation = "Always";
19 &AuthorizationId = "NMS Interface";
20 }
21 &CreationDateTime = formatDTNow();
22 @BODId = getGuid();
23 &BODId = @BODId;
24 }
25 &DataArea
26 {
27 &ExternalNumber = "NMS:"+ $E.outageHdl.idx;
28 # CreationDateTime is outageTime which is
29 # either when the first customer called
30 # or when the device was opened in the model
31 &CreationDateTime=formatDateTime($E.outageTime);
32 &Device:S = $E.devAlias;
33 &Address:S = substring($E.dispAddress, 0, 100);
34 sqlselect @devPhases, @fuseSize, @winter_load, @summer_load |
phase_designation, fuse_size, kva_lod_win, kva_lod_sumr |
classTable($E.devHdl.cls) | "where h_idx = " | $E.devHdl.idx;
35 &DevPhases = @devPhases;
36 &FuseSize = @fuseSize;
37 &WinterLoad = @winter_load;
38 &SummerLoad = @summer_load;
39 &NumCustOut:S = $E.customersOut;
40 &CallerName = $I.0.getCustomerName;
41 &CallerAddr = $I.0.getAddrStreet + " " + $I.0.getAddrCity;
42 &CallerPhone = $I.0.getCustomerPhone;
43 &CallerClues = $I.0.getShortDesc;
44 &CallerDevice = $I.0.getDeviceAlias;
45 }
46 $O.BODId = @BODId;
47 }
Line 1 declares the document to be an output document named 'Job'. The name is used in diagnostics, and when a document is invoked in a 'triggerOutputDoc' function call (see below).
Line 2 contains three specifications, and illustrates that more than one specification can be placed on one line.
The first specifies the message queue that the document will be sent out on. The specification assigns the queue to be the value of the external data field named 'OutRequestQueue' in the global configuration object. The queue name is available to the rest of the document in the variable '@queue', and could be changed, if required.
The second associates the document with the order object. Therefore this document will be used to hold the values of all the elements to be used for change detection when the event is updated with an SRSoutput message.
The third specifies that the message should be marked as persistent when placed on the queue. Not yet delivered messages are lost when the MQ server stops, if they are not marked as persistent.
Line 3 specifies a trigger, named 'triggerCreate' for the document, which causes an order to be created. It does not have the 'send on change' flag, so change detection is not in effect when this trigger is fired. The trigger specification, between '<' and '>' indicates when the trigger should be evaluated to determine whether it should be fired. In this case the arrival of an asynchronous SRSoutput message causes the trigger to be evaluated. The expression following the '=' is a boolean expression that fires the trigger when it evaluates to true. There may be more than one trigger for an output document. The values of the triggers are available to the rest of the document in variables with the same names as the triggers.
Line 3 also illustrates that a specification can span multiple lines.
Line 4 specifies a trigger, named 'triggerUpdate' for the document, which causes an order to be updated after it has been created. It has the 'send on change' flag, so change detection is in effect when this trigger is fired. The trigger specification, between '<' and '>' indicates when the trigger should be evaluated to determine whether it should be fired. In this case the arrival of an asynchronous SRSoutput message causes the trigger to be evaluated. The expression following the '=' is a boolean expression that fires the trigger when it evaluates to true. There may be more than one trigger for an output document. The values of the triggers are available to the rest of the document in variables with the same names as the triggers.
The '{' on line 5 and the '}' on line 47 enclose the body of the document.
Line 6 sets a default value for the variable @docType, which will be used later to set the root element tag.
Line 7 controls whether lines 9 and 10 are evaluated, depending on which trigger fired. If the triggerCreate trigger fired, 9 and 10 will be evaluated.
Line 9 changes the value of the @docType variable to reflect that the order is new.
Line 10 creates a new order object to save the values of the element's data for change detection.
Line 12 contains the root element tag and attributes. The root element differs from other elements in that the element's tag is specified by the value of the expression to the right hand side of the '=', in this case the value of the variable @docType. The reason for this is so that the same output document can be used for multiple message types, for example to create an order and to update the order. In this example, the 'environment' attribute is set to the value of the external data field named 'environment' in the global configuration object. The root element statement can be anywhere in the output document. All other elements appear in the generated XML in the order that they are within the output document.
Lines 13 to 24 define the 'ApplicationArea' element, with 3 sub-elements, one of which has 3 sub-elements.
The elements on lines 17 to 19 show how constants can be declared. On line 17 the 'NMS' is not surrounded by double quotes ("), because it only contains alphanumeric characters. On line 18 the 'Always' is surrounded by quotes, this acceptable, but not necessary because it only contains alphanumeric characters. On line 19 the 'NMS Interface' must be surrounded by quotes, because it contains a space.
The value of the element on line 21 is supplied by the 'formatDTNow' function that formats the current data and time BOD format CCYY-MM-DDThh:mm:ss.
Line 22 assigns a globally unique id to the variable 'BODId' for use on lines 23 and 46.
Lines 25 to 45 define the 'DataArea' element, with 15 sub-elements.
Line 27 assigns the concatenation of a constant (in quotes) with the event's index.
Lines 28 to 30 are comments and are ignored. Everything between a '#' and the end of a line, inclusive, is a comment and is ignored.
Line 31's element is assigned the time the outage began in the format CCYY-MM-DDThh:mm:ss.
Line 32's element is assigned the alias (name) of the event's interrupting device. Because the 'send on change' flag (S) is present, a change to this element's data will cause the XML to be sent to the MDS.
Line 33's element is assigned the address of the event, truncated to 100 characters. Because the 'send on change' flag (S) is present, a change to this element's data will cause the XML to be sent to the MDS.
Line 34 reads four columns of the interrupting device's facilities (attribute) table. The function 'classTable' supplies the name of the table.
Lines 35 to 38 assigns the values read from the database in line 33 to the appropriate elements.
Line 39's element is set to the number of customers affected by the outage. Because the 'send on change' flag (S) is present, a change to this element's data will cause the XML to be sent to the MDS.
Lines 40 to 44 use the external object 'Incidents' to access customer call data. As there are potentially many incidents associated with an event, the dml has to specify which incident to use. The second component of the name, between the first and second period (.) is the offset into the array of incidents, in this case zero. The last component of the name is the name of the data access method in the Incident class. These examples access the first customer's name, street address, city, phone number, clues, and transformer name. The incidents are normally ordered by the time that they called to report a problem, with the oldest first. If another ordering is required, by total priority for example, the sortIncidents() function can be used to change the order.
Line 46 saves the document's globally unique id in the external object for use later in another document.
The XML generated by this output document would look similar to the following:
<CreateJob environment="Test" revision="1.0.0">
<ApplicationArea>
<Sender>
<Component>NMS</Component>
<Confirmation>Always</Confirmation>
<AuthorizationId>NMS Interface</AuthorizationId>
</Sender>
<CreationDateTime>2003-05-01T13:36:13-05:00</CreationDateTime>
<BODId>guid</BODId>
</ApplicationArea>
<DataArea>
<ExternalNumber>NMS2010</ExternalNumber>
<CreationDateTime>2003-05-01T13:26:13-05:00</CreationDateTime>
<Device>XFM12345678</Device>
<Address>5800 Yonge St. North York</Address>
<DevPhases>A</DevPhases>
<FuseSize>100</FuseSize>
<WinterLoad>40</WinterLoad>
<SummerLoad>45</SummerLoad>
<NumCustOut>4</NumCustOut>
<CallerName>M.J. McLaughlin</CallerName>
<CallerAddr>5802 Yonge St. North York</CallerAddr>
<CallerPhone>416 555-1212</CallerPhone>
<CallerClues>NC</CallerClues>
<CallerDevice>XFM12345678</CallerDevice>
</DataArea>
</CreateJob>
An Input Document
The following is an example of an Input Document that processes a document containing completion data for an order. Various lines are numbered to allow reference to them in the explanation below. The numbers are not part of the syntax.
 
1 InputDoc CompletionData
2 queue=$G.InRequestQueue;
3 &RootElement<environment=$G.environment; revision="1.0.0";> =
4 FieldReportSave;
5 BasePath=DataArea;
6 {
7 &JobNumber:R;
8 &Crew
9 {
10 &CrewKey
11 {
12 &CrewName::"MDS";
13 }
14 }
15 &CompletionData
16 {
17 &System:R;
18 &Type:R;
19 &Failure:R;
20 &Cause:R;
21 &InterruptDev:R;
22 &Action:R;
23 &OtherAction::Other;
24 &RestoredTime;
25 &CustomerCaseNotes:::CCN;
26 }
27
28 if (!findOrder(externalId, &JobNumber))
29 {
30 stop;
31 }
32
33 @action=(&CompletionData/Action == "Other")
? &CompletionData/OtherAction
: &CompletionData/Action;
34 @restoredTime = decodeDateTime(&CompletionData/RestoredTime);
35 sqlupdate picklist_info_upd_tr |
system_om, type_om,
failure_om, cause_om,
interrupt_dev_om, action_text,
crew_restore |
&CompletionData/System, &CompletionData/Type,
&CompletionData/Failure, &CompletionData/Cause,
&CompletionData/InterruptDev, @action,
@restoredTime |
ref_id | $O.event.idx;
 
36 # call JMS::setCaseNoteInfo if appropriate
37 if (isSet(&CCN))
38 {
39 setCaseNoteInfo(getCaseNotesForEvent($O.event) + " " + &CCN);
40 }
41 # set no dtr flag if appropriate
42 if (isIn(&CompletionData/Type, "Customer Trouble",
43 "Other Utilities",
44 "Scheduled/Customer Notified"))
45 {
46 sqlupdate picklist_info_upd_tr | no_dtr_flag | Y |
ref_id | $O.event.idx;
47 }
 
# log change to event
48 @reason_for_update="Completion Information for Job " +
&JobNumber + " from MDS";
49 sqlinsert picklist_completion_log |
ref_id, who,
reason_for_update, when |
$O.event.idx, &Crew/CrewKey/CrewName,
@reason_for_update, time();
50
51 }
Line 1 declares the document to be an input document named 'CompletionData'.
Line 2 specifies the message queue that the document will be received on. The statement assigns the queue to be the value of the external data field named 'InRequestQueue' in the global configuration object.
Line 3 contains the root element tag and attributes. The root element differs from other elements in that the element's tag is specified by the value of the expression to the right hand side of the '=', in this case 'FieldReportSave'. The 'environment' attribute is set to the value of the external data field named 'environment' in the global configuration object. In contrast with output documents, the root element statement is in the header of the input document.
A message arriving on the message queue with the name specified on line 2, and with a root element tag and attributes as specified on line 3, triggers the processing of the message by the input document.
Line 5 specifies the base element's tag. The base element specifies the sub-element of the root element at which to start processing the elements specified in the body of the input document. The base element is optional, but is convenient in that it reduces the element nesting level in the body of the input document.
The '{' on line 6 and the '}' on line 51 enclose the body of the document.
Lines 7 to 26 define the tags for the elements that will be processed by the input document.
Line 7 defines a required element 'JobNumber'. The 'R' in the flags field of the element definition indicates that the element must be present in the input XML for the document to be processed. All required elements must be present, otherwise the XML will be ignored.
Line 12 defines an optional element 'CrewName', a sub-element of 'CrewKey', which is in turn a sub-element of 'Crew'. The element has a default value of 'MDS', which is the value used by references to the element in the rest of the document, when the element is not present. If a default value is not present, missing elements have a value of the empty string.
Lines 15 to 26 define the 'CompletionData' element, which has 9 sub-elements, some of which are required.
If all the required elements are present, the data can be processed.
Line 28 calls the 'findOrder' function that finds the order object with an 'externalId' field equal to the JobNumber supplied in the XML. This function returns a boolean indicating whether such an order object was found, or not. This result is inverted by the '!' so that line 30 is executed if 'findOrder' fails. Line 30 is a stop statement, which causes the processing of the document to terminate.
Line 33 sets the variable 'action' to either the contents of the 'OtherAction' element or the 'Action' element, depending on whether 'Action' has a value of 'Other' or not. Both these elements are sub-elements of the 'CompletionData' element. A reference to a sub-element takes the form '&grandparent/parent/subelement'.
Alternatively, an element can be named to make the references more succinct. The element definition of 'CustomerCareNotes' with a name of "CCN" on line 25, and the references to it on lines 37 and 39 are an example of this.
Line 34 converts the time in the element 'RestoredTime' into a format suitable to be passed to the database, and saves it in the variable 'restoredTime'.
Line 35 saves the values of 5 elements and 2 variables in the 'picklist_info_upd_tr' table in the database using a sqlupdate statement. This table has a key column 'ref_id' that is set to the order's event's index number. If aggregate processing has been configured, and the intention is to save the data in the database for all events in the aggregation, the function 'picklistInfoUpdTr' would be more appropriate.
Line 37 tests whether the element named 'CCN' (the 'CustomerCaseNotes' element in 'CompletionData'), was present in the input XML, using the function 'isSet'. If the element was set line 39 is executed . The function call to 'getCaseNotesForEvent' in the parameter list of the call to 'setCaseNoteInfo', calls an Oracle Utilities Network Management System API to read the current value of the order's event case notes. The value returned is concatenated with a space and the value of the CCN element. The resulting value is saved to the event's case notes using the function 'setCaseNoteInfo'.
Lines 42 to 47 set the 'no_dtr_flag' column in the 'picklist_info_upd_tr' table to 'Y', if the 'CompletionData/Type' element indicates that the trouble was not with the utility's equipment. The function 'isIn' returns true if its first parameter matches any one of the rest of its parameters, false otherwise
Lines 48 and 49 logs the change to the event by inserting a row into the picklist_completion_log table. If aggregate processing has been configured, and the intention is to save the data in the database for all events in the aggregation, the function 'picklistCompLog' would be more appropriate.
The following XML would be processed by the example input document
<FieldReportSave environment="Test" revision="1.0.0">
<ApplicationArea>
<Sender>
<Component>MDS</Component>
<Confirmation>Never</Confirmation>
<AuthorizationId>MDS Interface</AuthorizationId>
</Sender>
<CreationDateTime>2003-05-01T14:30:17-05:00</CreationDateTime>
<BODId>guid</BODId>
</ApplicationArea>
<DataArea>
<JobNumber>MDS7704</JobNumber>
<CompletionData>
<System>4KV</System>
<Type>Lateral</Type>
<Failure>Fuse</Failure>
<Cause>Animal</Cause>
<InterruptDev>XFM12345678</InterruptDev>
<Action>Fuse replaced</Action>
<CustomerCaseNotes>Temporary Repair: Scheduled for Tuesday</CustomerCaseNotes>
</CompletionData>
</DataArea>
</FieldReportSave>