configurationengine/doc/plugins/ruleml-plugin/ruleplugin.rst
changeset 3 e7e0ae78773e
parent 0 2e8eeb919028
equal deleted inserted replaced
2:87cfa131b535 3:e7e0ae78773e
     1 User guide for Rule Plugin usage in ConE
     1 User guide for Rule Plugin usage in ConE
     2 ----------------------------------------
     2 ========================================
       
     3 
       
     4 .. note::
       
     5     RuleML v3 is now the officially supported RuleML version.
       
     6     Support for versions 1 and 2 is still present in ConE, but they will not
       
     7     be maintained anymore. If you have e.g. a RuleML v2 file and require some
       
     8     new functionality, the new functionality will be added to RuleML v3 and
       
     9     you will need to update your RuleML file to use version 3.
       
    10     
       
    11     Updating should be easy, since the biggest change is setting reference
       
    12     syntax. Simply add ``${}`` around all setting references in the rules.
     3 
    13 
     4 Introduction
    14 Introduction
     5 '''''''''''''
    15 ------------
     6 This page describes how to use ConE Rule plugin. With rule plugin one may set rule configuration 
    16 This page describes how to use the ConE Rule plugin. The plug-in provides
     7 for the values in the confml. So for ex. one may have a case where is one confml value is been setted
    17 support for RuleML files, which can be used to execute rules during output
     8 and one may create a rule configuration that if this value is for ex. 'foo' then some other value is
    18 generation. The main use for RuleML is modifying the values of ConfML settings
     9 'bar'. Value may be required or configures. 
    19 on run-time based on the values of other settings.
    10 
    20 
    11 
    21 The rule plug-in registers the ImplML namespace for defining rules, and the
    12 Creating a rule configuration file
    22 RuleML-specific file extension:
    13 ''''''''''''''''''''''''''''''''''
    23 
    14 Create a new file a example.ruleml and set it's file encoding to UTF-8.
    24   * Namespace: ``http://www.s60.com/xml/ruleml/3``
    15 Place the file in the impml folder in configuration project.
    25   * File extension: ``ruleml``
    16 The file is a XML base file. 
    26 
    17 First set the encoding tag 
    27 .. note::
    18 
    28 
    19 .. code-block:: xml
    29    More information about :ref:`file extensions <implml-file-extensions>`. 
    20 
    30 
    21   <?xml version="1.0" encoding="UTF-8"?>* 
    31 Usage
    22 
    32 -----
    23 and then create a root tag
    33 
    24 
    34 A RuleML file is simply an XML file that defines a set of rules. For example:
    25 .. code-block:: xml
    35 
    26 
    36 .. code-block:: xml
    27   <ruleml xmlns="http://www.s60.com/xml/ruleml/1">*
    37 
       
    38     <?xml version="1.0" encoding="UTF-8"?>
       
    39     <ruleml xmlns="http://www.s60.com/xml/ruleml/3">
       
    40         <rule>${SomeFeature.SomeSetting} == 'testing' configures ${SomeFeature.SomeOtherSetting} = 5</rule>
       
    41         <rule>${SomeFeature.SomeSetting} == 'xyz' configures ${SomeFeature.SomeOtherSetting} = 6</rule>
       
    42     </ruleml>
       
    43 
       
    44 The above example sets the value of the setting ``SomeFeature.SomeOtherSetting``
       
    45 to the integer value ``5`` or ``6`` if the value of ``SomeFeature.SomeSetting`` is
       
    46 one of the strings ``testing`` or ``xyz``.
       
    47 
       
    48 Rules can also contain multiple operations in a single rule, and can span
       
    49 multiple lines to make the rule more readable. For example:
       
    50 
       
    51 .. code-block:: xml
       
    52 
       
    53     <?xml version="1.0" encoding="UTF-8"?>
       
    54     <ruleml xmlns="http://www.s60.com/xml/ruleml/3">
       
    55         <rule>
       
    56             ${SomeFeature.SomeSetting} == 'testing' configures
       
    57                 ${SomeFeature.SomeOtherSetting} = 5 and
       
    58                 ${SomeFeature.SomeOtherSetting2} = 6 and
       
    59                 ${SomeFeature.SomeOtherSetting3} = 7
       
    60         </rule>
       
    61     </ruleml>
       
    62 
       
    63 Sometimes the case is that the rule should be executed always, regardless of
       
    64 the values of any other settings. To do this you can simply specify ``True``
       
    65 as the left-hand side expression:
       
    66 
       
    67 .. code-block:: xml
       
    68 
       
    69     <?xml version="1.0" encoding="UTF-8"?>
       
    70     <ruleml xmlns="http://www.s60.com/xml/ruleml/3">
       
    71         <rule>True configures ${SomeFeature.SomeOtherSetting} = 'Hello!'</rule>
       
    72     </ruleml>
       
    73 
       
    74 Python expressions in rules
       
    75 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
       
    76 
       
    77 RuleML has an extension to the basic rule syntax, which allows any `Python <http://www.python.org/doc/2.5/>`_
       
    78 expressions to be used. These can be used to create more complex logic into
       
    79 rules than is possible with standard rule expressions. The Python expressions
       
    80 are defined between ``{%`` and ``%}``, and can be used in place of normal
       
    81 value expressions.
       
    82 
       
    83 You can access global ruleml namespace, from which you can find Configuration and Generation Context of the active execution.
       
    84 
       
    85  * ruleml.configuration - links to `Configuration <../../../docbuild/epydoc/cone.public.api.Configuration-class.html>`_ object.
       
    86  * ruleml.context - links to `Generation Context <../../../docbuild/epydoc/cone.public.plugin.GenerationContext-class.html>`_ object.
    28  
    87  
    29 give a set of rules for ex. 
    88 
    30  
    89 *Examples of using Python scripts inside ruleml files:*
    31 .. code-block:: xml
    90 
    32 
    91 .. code-block:: xml
    33   <rule>mms.imagesize == 'large' configures pd.ref1 = True and pd.ref2 = True</rule>*
    92 
    34  
    93     <?xml version="1.0" encoding="UTF-8"?>
    35 and close the ruleml tag.
    94     <ruleml xmlns="http://www.s60.com/xml/ruleml/3">
    36 
    95         <rule>
    37 One may say use several boolean operators for the configuration rule like for ex.
    96             True configures ${SomeFeature.SomeOtherSetting} = {% 2 ** 16 %}
    38  
    97         </rule>
    39 .. code-block:: xml
    98     </ruleml>
    40 
    99 
    41   and, or, ==, !=* 
   100 This sets the value of ``SomeFeature.SomeOtherSetting`` to the evaluated value
    42  
   101 of the Python expression ``2 ** 16``, which is 65536.
    43 Like for ex.
   102 
    44 
   103 Obviously, simple expressions like this cannot do much, but an expression can
    45 .. code-block:: xml
   104 also be a function call, and functions can do almost anything. Functions (and 
    46 
   105 also any other globals) can be specified using ``<eval_globals>`` elements.
    47   <rule>mms.imagesize == 'large' configures pd.ref1 = True and pd.ref2 = True</rule>*
   106 For example:
    48  
   107 
    49 means that if reference link mms/imagesize  in some confml file is set to large then reference 
   108 .. code-block:: xml
    50 link pd/ref1 value is true and pd/ref2 value is set to true also.
   109 
    51 
   110     <?xml version="1.0" encoding="UTF-8"?>
    52 **All in all one may create a dependency like project configuration with ruleml files.**  
   111     <ruleml xmlns="http://www.s60.com/xml/ruleml/3">
    53 
   112         <rule>
    54 Ruleml version 2 adds support for calling `Python <http://www.python.org/doc/2.5/>`_ expressions from rules. Python expression are defined between ``{%`` and ``%}``:
   113             True configures ${SomeFeature.SomeOtherSetting} = {% power(2, 16) %}
    55 
   114         </rule>
    56 .. code-block:: xml
   115         <eval_globals>
    57 
   116     def power(x, y):
    58   <rule>feat1.setting2 == True configures feat2.setting2 = {% ${feat3.setting2} %}</rule>
   117         result = 1
    59 
   118         for i in xrange(y):
    60 Expression return a result, that can be used in rule e.g. to set a value to some setting in configuration. These expression can be used to create more complex logic into rules that is not possible with standard rule expressions. Inside eval expressions features and feature's values can be accessed by following syntax:
   119             result *= x
    61 
   120         return result
    62 Accesses to the value::
   121         </eval_globals>
    63 
   122     </ruleml>
    64   ${Feature.Setting}
   123 
    65 
   124 This does the same thing as the previous example, except that it uses a custom
    66 Accesses to the feature object::
   125 function to do it.
    67 
   126 
    68   @{Feature.Setting}
   127 It is also possible to use standard Python libraries or the
    69 
   128 `ConE API <../../epydoc/index.html>`_ from ``<eval_globals>``, and also
    70 Python functions or constants that can be accessed inside expressions can be defined by ``<eval_globals>`` elements:
   129 some RuleML-specific things. Ruleml has all data from 
    71 
   130 Configuration and Generation Context classes of the active execution. For example:
    72 .. code-block:: xml
   131 
    73 
   132 .. code-block:: xml
    74   <eval_globals>
   133 
    75   def my_function1(attribute):
   134     <?xml version="1.0" encoding="UTF-8"?>
    76       return attribute + 1
   135     <ruleml xmlns="http://www.s60.com/xml/ruleml/3">
    77   </eval_globals>
   136         <rule>
    78   
   137             True configures ${SomeFeature.SomeOtherSetting} = {% power(2, 16) %}
    79   <eval_globals>CONST_1 = "my constant"</eval_globals>
   138         </rule>
    80   
   139         <eval_globals>
    81   <eval_globals file=".scripts/evals_in_file.py"/>
   140     # Import the standard library urllib2 to do operations on URLs
    82   
   141     import urllib2
    83 Definitions can be inside <eval_globals> elements or definitions can be in separate file referenced with ``file`` attribute.
   142     
    84 The path specified in this attribute is relative to the RuleML implementation file. So, for example, if your implementation
   143     # Import the ConE API
    85 file's location is ``some/layer/implml/my_rules.ruleml``, the actual path specified in the above example would be
   144     from cone.public import api
    86 ``some/layer/implml/.scripts/evals_in_file.py``. It is recommended to place the scripts under a directory beginning
   145     
    87 with a dot, so that the plug-in loader does not attempt to load the .py file as an implementation (files and directories beginning
   146     def get_project_path():
    88 with a dot are ignored in the implementation loading phase).
   147         # The current configuration is available in ruleml.configuration
    89 
   148         config = ruleml.configuration
    90 Running
   149         
    91 '''''''''''''''''''''
   150         # Return the path of the storage the current project is in
    92 
   151         project = config.get_project()
    93 ::
   152         return project.storage.get_path()
    94 
   153         </eval_globals>
    95   cone generate -p someproject.cpf -o c:/temp/coneoutput -i rulemlfile.ruleml
   154     </ruleml>
    96 
   155     
    97 Generates files out of configuration file and takes the implementation rulemlfile.ruleml in concern,
   156 
    98 and the output is to been set to -o given folder 
   157 In this example configuration is got from ruleml. Generation Context can be 
    99 
   158 accessed in the same way, ruleml.context will have all data stored in the 
   100 for more example see the cone documentation
   159 Generation Context object.
   101 
   160 
   102 Examples
   161 Generation Context values can be accessed inside the Python expressions using the
   103 '''''''''
   162 ruleml.context like ruleml.context.output.
   104 
   163 
   105 
   164 This example uses the Generation Context to get defined output folder. 
   106 **Ruleml version 1 file example**
   165 See how to access the data from the code example below.
   107 
   166 
   108 .. code-block:: xml
   167 .. code-block:: xml
   109 
   168 
   110   <?xml version="1.0" encoding="UTF-8"?>
   169     <?xml version="1.0" encoding="UTF-8"?>
   111   <ruleml xmlns="http://www.s60.com/xml/ruleml/1">
   170     <ruleml xmlns="http://www.s60.com/xml/ruleml/3">
   112   <rule>imaker.imagetarget configures imakerapi.outputLocation = imaker.imagetarget</rule>
   171         <rule>
   113   <rule>mms.imagesize == 'large' configures pd.ref1 = True and pd.ref2 = True</rule>
   172             True configures ${SomeFeature.output} = {% get_output_folder() %}
   114   <rule>mms.imagesize == 'small' configures pd.ref1 = False and pd.ref2 = True</rule>
   173         </rule>
   115   <rule>mms.imagesize == 'extrasmall' configures pd.ref1 = False and pd.ref2 = False</rule>
   174         <eval_globals>
   116   <rule>mms.imagesize == 'extralarge' configures pd.ref1 = True and pd.ref2 = False</rule>
   175           
   117   </ruleml>
   176     def get_output_folder():
   118 
   177         output = ruleml.context.output
   119 **What do the example ruleml file means**
   178         return output
   120 
   179         </eval_globals>
   121 The example file set the values upon the image size. First it sets the iMaker output
   180     </ruleml>
   122 location target and then it starts to set the mms message image size settings. So if for ex.
   181 
   123 *mms/imagesize* refence link value in confml file is set to *extralarge* then the value of
   182 
   124 *pd/ref1* is set to *true* and the value *pd/ref2* is set to false.
   183 Accessing ConfML values inside Python expressions
   125 
   184 '''''''''''''''''''''''''''''''''''''''''''''''''
   126 
   185 
   127 **Ruleml version 2 file example**
   186 ConfML setting values can be accessed inside the Python expressions using the
   128 
   187 same notation as elsewhere in the rules, i.e. using ``${`` and ``}``.
   129 .. code-block:: xml
   188 For example:
   130 
   189 
   131   <?xml version="1.0" encoding="UTF-8"?>
   190 .. code-block:: xml
   132   <ruleml xmlns="http://www.s60.com/xml/ruleml/2">
   191 
   133   <rule>feat1.setting1 == 'somevalue' configures feat2.setting1 = {% len( ${feat3.setting1} ) %}</rule>
   192     <?xml version="1.0" encoding="UTF-8"?>
   134   <rule>feat1.setting2 == True configures feat2.setting2 = {% my_function1( ${feat3.setting2} ) %}</rule>
   193     <ruleml xmlns="http://www.s60.com/xml/ruleml/3">
   135   <rule>feat1.setting3 == True configures feat2.setting3 = {% CONST_1 %}</rule>
   194         <rule>
   136   <rule>{% my_function2( ${feat1.setting4} ) %} configures feat2.setting4 = False</rule>
   195             ${SomeFeature.SomeSetting} == 'testing' configures ${SomeFeature.SomeOtherSetting} = {% ${SomeFeature.SomeSetting}.upper() %}
   137   <rule>{% @{feat1.setting5}.get_type() %} == 'int' configures feat2.setting5 = 'integer'</rule>
   196         </rule>
   138   <rule>feat1.setting6 == True configures feat2.setting6 = {% '0x%08X' % ${feat2.setting6} %}</rule>
   197     </ruleml>
   139   <eval_globals>
   198 
   140   def my_function1(attribute):
   199 This sets the value of ``SomeFeature.SomeOtherSetting`` to 'TESTING'.
   141       return attribute + 1
   200 
   142   def my_function2(attribute):
   201 Accessing feature objects inside Python expressions
   143       if attribute == 'abc':
   202 '''''''''''''''''''''''''''''''''''''''''''''''''''
   144           return True
   203 
   145       else:
   204 Sometimes it is necessary to access the actual feature (or setting) object that
   146           return False
   205 ConE uses internally to perform more complex operations. This can be done
   147   </eval_globals>
   206 similarly to accessing the setting values, the only difference is that the
   148   <eval_globals>
   207 setting reference needs to be surrounded by ``@{}``. For example:
   149   CONST_1 = "my constant"
   208 
   150   </eval_globals>
   209 .. code-block:: xml
   151   <eval_globals file=".scripts/evals_in_file.py"/>
   210 
   152   </ruleml>
   211     <?xml version="1.0" encoding="UTF-8"?>
   153 
   212     <ruleml xmlns="http://www.s60.com/xml/ruleml/3">
   154 XSD
   213         <rule>
   155 '''''''''
   214             True configures ${SomeFeature.SomeOtherSetting} = {% get_location(@{SomeFeature.SomeSetting}) %}
   156 
   215         </rule>
   157 Ruleml version 1: :download:`ruleml.xsd </xsd/ruleml.xsd>`
   216         <eval_globals>
   158 
   217     from cone.public import api
   159 Ruleml version 2: :download:`ruleml2.xsd </xsd/ruleml2.xsd>`
   218     
       
   219     def get_location(setting):
       
   220         parent_config = setting._find_parent(type=api.Configuration)
       
   221         return parent_config.get_path()
       
   222         </eval_globals>
       
   223     </ruleml>
       
   224 
       
   225 This example uses the ConE API to find the location (ConfML file) where the
       
   226 given setting is defined.
       
   227 
       
   228 
       
   229 Defining functions in a separate .py file
       
   230 '''''''''''''''''''''''''''''''''''''''''
       
   231 
       
   232 Defining the Python functions used in the rules in an ``<eval_globals>`` element
       
   233 can quickly become unwieldy for larger functions:
       
   234 
       
   235 - Things like ``<`` need to escaped using the corresponding XML entity references
       
   236 - Syntax highlighting is not available
       
   237 - Writing and running unit tests for the functions is not possible
       
   238 
       
   239 For these reasons, the code of an ``<eval_globals>`` element can also be
       
   240 specified in a separate Python file using the ``file`` attribute. For example:
       
   241 
       
   242 .. code-block:: xml
       
   243 
       
   244     <?xml version="1.0" encoding="UTF-8"?>
       
   245     <ruleml xmlns="http://www.s60.com/xml/ruleml/3">
       
   246         <rule>
       
   247             True configures ${SomeFeature.SomeOtherSetting} = {% some_very_complex_operation(
       
   248                 @{SomeFeature.SomeSetting1},
       
   249                 ${SomeFeature.SomeSetting2},
       
   250                 ${SomeFeature.SomeSetting3}) %}
       
   251         </rule>
       
   252         <eval_globals file="scripts/complex_function.py"/>
       
   253     </ruleml>
       
   254 
       
   255 The path specified in the ``file`` attribute is relative to the implementation
       
   256 file where the rule is specified, so if the RuleML file in this example was
       
   257 located in ``assets/example/implml/some_rule.ruleml``, the referenced Python
       
   258 file would be ``assets/example/implml/scripts/complex_function.py``.
   160 
   259 
   161 FAQ
   260 FAQ
   162 '''''''''
   261 ---
   163 This will be updated based on the questions.
   262 This will be updated based on any questions.