At this point, the custom condition is ready for use by your business managers. Optionally, however, you could extend the Scenarios module’s grammar expression editor to provide more elegant handling of the new custom condition in the ACC. This process involves two steps:
Create an XML file that defines the custom expression grammar. In our example, the file is
astroweb/astroweb-grammar.xml
.Add a grammar registry entry specifying the location of the expression grammar XML file to the
scenarioManager.xml
file.
The next sections in this chapter describe these steps.
For detailed information on options for extending the expression editor for use in the Scenarios module and other ATG products, refer to the next chapter, Configuring the ATG Expression Editor.
Creating an Expression Grammar Definition File
The following sample shows the file astroweb/astroweb-grammar.xml
.
<?xml version="1.0" encoding="UTF-8" standalone="no" ?> <?xcl-stylesheet resource="atg/ui/scenario/expression/scenario-grammar.xsl"?> <?xcl-stylesheet resource="atg/ui/expreditor/xcl/grammar.xsl"?> - <!-- This grammar definition supplies the details of how our example's custom action and custom condition will be treated in the UI. --> <context> <!-- Define the grammar of action "logInfo". Our intention is to constrain both operands to literals, rather than general scenario expressions, and to require the logInteger to be unsigned. --> <sequence id="action-logInfo"> <!-- Attach an XML template to this grammar node, specifying the SDL that it will emit. This template will generate an <action-name> tag inside the enclosing <action> tag, followed by SDL emitted by children of this node. --> <xml-template> <action-name>logInfo</action-name> <apply-xml-templates /> </xml-template> <!-- Provide a leading token that will show up as a choice in the Actions menu of the scenario editor. --> <token> <description>Log test data</description> </token> <!-- include a token describing the string to be logged --> <token> <description>with label</description> </token> <!-- then, a literal supplying the logString parameter --> <literal> <xml-template> <action-param name="logString"> <constant> <apply-xml-templates /> </constant> </action-param> </xml-template> <required /> </literal> <!-- then a token describing the int to be logged --> <token> <description>and value</description> </token> <!-- then, a literal supplying the integer parameter. The <default> tag is required for all non-String literals as it determines the data type. --> <literal> <xml-template> <action-param name="logInteger"> <constant> <apply-xml-templates /> </constant> </action-param> </xml-template> <unsigned-integer-editor /> <required /> <default> <value type="java.lang.Integer">1</value> </default> </literal> </sequence> <!-- Define the grammar of condition "moonPhase". Note that the id of this grammar element is the prefix "condition-", followed by the condition name given in scenarioManager.xml. We would like to support the following syntax: Moon's phase is (new | waxing | full | waning) (on DATE-EXPR | now) The MoonFilter class expects two operands; the first operand is a stringified integer relating to the choice of phase (new, waxing, ...), while the second is an arbitrary expression of type Date. --> <sequence id="condition-moonPhase"> <!-- Attach an XML template to this grammar node, specifying the SDL that it will emit inside an enclosing <condition> tag. This template says that a <filter operator="moonPhase"> tag should enclose all XML generated by children of this grammar node. --> <xml-template> <filter operator="moonPhase"> <apply-xml-templates /> </filter> </xml-template> <!-- Provide a leading token that will show up as a choice in the Conditions menu of the scenario editor. --> <token> <description>Moon's phase is</description> </token> <!-- Provide a choice of tokens for the moon phase, the first condition operand. Each token's <description> governs how it is presented in the scenario editor choice list, while each token's XML template supplies an SDL fragment defining a constant value, to be generated when that token is the current choice. --> <choice> <!-- (new | waxing | full | waning) --> <token> <xml-template> <constant type="java.lang.Integer">0</constant> </xml-template> <description>new</description> </token> <token> <xml-template> <constant type="java.lang.Integer">1</constant> </xml-template> <description>waxing</description> </token> <token> <xml-template> <constant type="java.lang.Integer">2</constant> </xml-template> <description>full</description> </token> <token> <xml-template> <constant type="java.lang.Integer">3</constant> </xml-template> <description>waning</description> </token> </choice> <!-- Provide a choice of two possible values for the second operand of the condition. The first choice is a token whose displayed description is "now", which is a short hand for an SDL expression equivalent to "Today's timeAsDate". The second choice is an arbitrary scenario expression of type java.util.Date. Note that the "now" choice must come first, because the SDL for "now" can match either of the two choices' templates; we want it to match the more specific of the two. --> <choice> <!-- (on DATE-EXPR | now) --> <token> <!-- now --> <xml-template> <jndi-property> <jndi-url>dynamo:/atg/dynamo/service/CurrentDate</jndi-url> <property-name>timeAsDate</property-name> </jndi-property> </xml-template> <description>now</description> <!-- only show the word "now" in the dropdown choice list --> <hidden /> </token> <sequence> <!-- on DATE-EXPR --> <token> <editor-text>on</editor-text> <!-- show ellipsis in dropdown choice list only --> <description>on...</description> </token> <scenario-expression type="java.util.Date" /> </sequence> </choice> </sequence> </context>
Extending the Grammar Extension Class
Create an extension of the class atg.ui.scenario.expression.DefaultGrammarExtension
that simply identifies how to locate the grammar extension XML file, which in our example is astroweb/astroweb-grammar.xml
. The following sample shows the extension created for our custom condition:
package astroweb; import atg.ui.scenario.expression.*; public class AstrowebGrammarExtension extends DefaultGrammarExtension { //---------------------------------------- /** * Construct a grammar extension that references our example custom * expression grammar definition. */ public AstrowebGrammarExtension() { // Specify the grammar file. super("astroweb.astroweb-grammar"); // Note: the grammar file is specified with no suffix and with a // dot-qualified package name, since it is localized in a // ResourceBundle-like way. If the user's locale is en_US, for // instance, the following files will be searched for, in this // order: // // astroweb/astroweb-grammar_en_US.xml // astroweb/astroweb-grammar_en.xml // astroweb/astroweb-grammar.xml } }
Specifying the Location of the Expression Grammar XML File
The final step is to add a grammar registry entry to the scenarioManager.xml
file that specifies the location of the expression grammar XML file. The following sample shows the additions you would make to the scenarioManager.xml
file:
<grammar-registry>
<grammar-extension-file>astroweb.astroweb-grammar
</grammar-extension-file>
</grammar-registry>
Note that the grammar file is specified with no suffix and with a dot-qualified package name to make localization easier. If the user’s locale is en_US
, for instance, the following files will be searched for, in this order:
astroweb/astroweb-grammar_en_US.xml
astroweb/astroweb-grammar_en.xml
astroweb/astroweb-grammar.xml