0
|
1 |
User guide for Rule Plugin usage in ConE
|
3
|
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.
|
0
|
13 |
|
|
14 |
Introduction
|
3
|
15 |
------------
|
|
16 |
This page describes how to use the ConE Rule plugin. The plug-in provides
|
|
17 |
support for RuleML files, which can be used to execute rules during output
|
|
18 |
generation. The main use for RuleML is modifying the values of ConfML settings
|
|
19 |
on run-time based on the values of other settings.
|
0
|
20 |
|
3
|
21 |
The rule plug-in registers the ImplML namespace for defining rules, and the
|
|
22 |
RuleML-specific file extension:
|
0
|
23 |
|
3
|
24 |
* Namespace: ``http://www.s60.com/xml/ruleml/3``
|
|
25 |
* File extension: ``ruleml``
|
|
26 |
|
|
27 |
.. note::
|
|
28 |
|
|
29 |
More information about :ref:`file extensions <implml-file-extensions>`.
|
|
30 |
|
|
31 |
Usage
|
|
32 |
-----
|
|
33 |
|
|
34 |
A RuleML file is simply an XML file that defines a set of rules. For example:
|
0
|
35 |
|
|
36 |
.. code-block:: xml
|
|
37 |
|
3
|
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>
|
0
|
43 |
|
3
|
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:
|
0
|
50 |
|
|
51 |
.. code-block:: xml
|
|
52 |
|
3
|
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>
|
0
|
62 |
|
3
|
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:
|
0
|
66 |
|
|
67 |
.. code-block:: xml
|
|
68 |
|
3
|
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.
|
0
|
87 |
|
|
88 |
|
3
|
89 |
*Examples of using Python scripts inside ruleml files:*
|
0
|
90 |
|
|
91 |
.. code-block:: xml
|
|
92 |
|
3
|
93 |
<?xml version="1.0" encoding="UTF-8"?>
|
|
94 |
<ruleml xmlns="http://www.s60.com/xml/ruleml/3">
|
|
95 |
<rule>
|
|
96 |
True configures ${SomeFeature.SomeOtherSetting} = {% 2 ** 16 %}
|
|
97 |
</rule>
|
|
98 |
</ruleml>
|
0
|
99 |
|
3
|
100 |
This sets the value of ``SomeFeature.SomeOtherSetting`` to the evaluated value
|
|
101 |
of the Python expression ``2 ** 16``, which is 65536.
|
0
|
102 |
|
3
|
103 |
Obviously, simple expressions like this cannot do much, but an expression can
|
|
104 |
also be a function call, and functions can do almost anything. Functions (and
|
|
105 |
also any other globals) can be specified using ``<eval_globals>`` elements.
|
|
106 |
For example:
|
0
|
107 |
|
|
108 |
.. code-block:: xml
|
|
109 |
|
3
|
110 |
<?xml version="1.0" encoding="UTF-8"?>
|
|
111 |
<ruleml xmlns="http://www.s60.com/xml/ruleml/3">
|
|
112 |
<rule>
|
|
113 |
True configures ${SomeFeature.SomeOtherSetting} = {% power(2, 16) %}
|
|
114 |
</rule>
|
|
115 |
<eval_globals>
|
|
116 |
def power(x, y):
|
|
117 |
result = 1
|
|
118 |
for i in xrange(y):
|
|
119 |
result *= x
|
|
120 |
return result
|
|
121 |
</eval_globals>
|
|
122 |
</ruleml>
|
|
123 |
|
|
124 |
This does the same thing as the previous example, except that it uses a custom
|
|
125 |
function to do it.
|
|
126 |
|
|
127 |
It is also possible to use standard Python libraries or the
|
|
128 |
`ConE API <../../epydoc/index.html>`_ from ``<eval_globals>``, and also
|
|
129 |
some RuleML-specific things. Ruleml has all data from
|
|
130 |
Configuration and Generation Context classes of the active execution. For example:
|
|
131 |
|
|
132 |
.. code-block:: xml
|
0
|
133 |
|
3
|
134 |
<?xml version="1.0" encoding="UTF-8"?>
|
|
135 |
<ruleml xmlns="http://www.s60.com/xml/ruleml/3">
|
|
136 |
<rule>
|
|
137 |
True configures ${SomeFeature.SomeOtherSetting} = {% power(2, 16) %}
|
|
138 |
</rule>
|
|
139 |
<eval_globals>
|
|
140 |
# Import the standard library urllib2 to do operations on URLs
|
|
141 |
import urllib2
|
|
142 |
|
|
143 |
# Import the ConE API
|
|
144 |
from cone.public import api
|
|
145 |
|
|
146 |
def get_project_path():
|
|
147 |
# The current configuration is available in ruleml.configuration
|
|
148 |
config = ruleml.configuration
|
|
149 |
|
|
150 |
# Return the path of the storage the current project is in
|
|
151 |
project = config.get_project()
|
|
152 |
return project.storage.get_path()
|
|
153 |
</eval_globals>
|
|
154 |
</ruleml>
|
|
155 |
|
0
|
156 |
|
3
|
157 |
In this example configuration is got from ruleml. Generation Context can be
|
|
158 |
accessed in the same way, ruleml.context will have all data stored in the
|
|
159 |
Generation Context object.
|
0
|
160 |
|
3
|
161 |
Generation Context values can be accessed inside the Python expressions using the
|
|
162 |
ruleml.context like ruleml.context.output.
|
0
|
163 |
|
3
|
164 |
This example uses the Generation Context to get defined output folder.
|
|
165 |
See how to access the data from the code example below.
|
0
|
166 |
|
|
167 |
.. code-block:: xml
|
|
168 |
|
3
|
169 |
<?xml version="1.0" encoding="UTF-8"?>
|
|
170 |
<ruleml xmlns="http://www.s60.com/xml/ruleml/3">
|
|
171 |
<rule>
|
|
172 |
True configures ${SomeFeature.output} = {% get_output_folder() %}
|
|
173 |
</rule>
|
|
174 |
<eval_globals>
|
|
175 |
|
|
176 |
def get_output_folder():
|
|
177 |
output = ruleml.context.output
|
|
178 |
return output
|
|
179 |
</eval_globals>
|
|
180 |
</ruleml>
|
0
|
181 |
|
|
182 |
|
3
|
183 |
Accessing ConfML values inside Python expressions
|
|
184 |
'''''''''''''''''''''''''''''''''''''''''''''''''
|
|
185 |
|
|
186 |
ConfML setting values can be accessed inside the Python expressions using the
|
|
187 |
same notation as elsewhere in the rules, i.e. using ``${`` and ``}``.
|
|
188 |
For example:
|
|
189 |
|
|
190 |
.. code-block:: xml
|
|
191 |
|
|
192 |
<?xml version="1.0" encoding="UTF-8"?>
|
|
193 |
<ruleml xmlns="http://www.s60.com/xml/ruleml/3">
|
|
194 |
<rule>
|
|
195 |
${SomeFeature.SomeSetting} == 'testing' configures ${SomeFeature.SomeOtherSetting} = {% ${SomeFeature.SomeSetting}.upper() %}
|
|
196 |
</rule>
|
|
197 |
</ruleml>
|
|
198 |
|
|
199 |
This sets the value of ``SomeFeature.SomeOtherSetting`` to 'TESTING'.
|
|
200 |
|
|
201 |
Accessing feature objects inside Python expressions
|
|
202 |
'''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
203 |
|
|
204 |
Sometimes it is necessary to access the actual feature (or setting) object that
|
|
205 |
ConE uses internally to perform more complex operations. This can be done
|
|
206 |
similarly to accessing the setting values, the only difference is that the
|
|
207 |
setting reference needs to be surrounded by ``@{}``. For example:
|
0
|
208 |
|
|
209 |
.. code-block:: xml
|
|
210 |
|
3
|
211 |
<?xml version="1.0" encoding="UTF-8"?>
|
|
212 |
<ruleml xmlns="http://www.s60.com/xml/ruleml/3">
|
|
213 |
<rule>
|
|
214 |
True configures ${SomeFeature.SomeOtherSetting} = {% get_location(@{SomeFeature.SomeSetting}) %}
|
|
215 |
</rule>
|
|
216 |
<eval_globals>
|
|
217 |
from cone.public import api
|
|
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:
|
0
|
234 |
|
3
|
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
|
0
|
243 |
|
3
|
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>
|
0
|
254 |
|
3
|
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``.
|
0
|
259 |
|
|
260 |
FAQ
|
3
|
261 |
---
|
|
262 |
This will be updated based on any questions.
|