1 <chapter id="producer_framework">
2 <title>The producer framework</title>
3 Please read the presentation of the <glossterm linkend="producers">producers</glossterm> concept
6 <section><title>How to use the <filename>producers.xml</filename> file</title>
7 [FIXME: this should be in the admin's guide, not here]
10 Please check the standard <filename>producers.xml</filename> file
11 for two fully commented, real-world examples :
12 the <code><nodedefinition name="Language"></code> node
13 and the <code><producer name="articles"></code> node.
16 <section><title>Introduction</title>
19 Mir allows admins to fully configure the producer tasks and set up
20 arbitrary producers through the <filename>producers.xml</filename> file.
24 Producers consist of "nodes". Every node has a specific function.
25 For example, it is possible to use a node to generate a file out of a template.
26 Or it is possible to use a node to enumerate over a collection of articles.
32 A producer is defined using a Producer tag:
34 <producer name="content"/>
36 This would define a producer named <code>content</code>.
39 In a producer, <emphasis>verbs</emphasis> must be defined.
40 Verbs are sub-tasks of a producer.
44 <producer name="content">
46 <verb name="new">
48 <verb name="all">
51 <producer name="content"/>
54 This would define a producer with verbs named <code>all</code> and <code>new</code>.
57 And also the specific nodes and their relationship should be specified:
61 <producer name="content">
63 <verb name="new">
65 <verb name="all">
70 generator="/producer/startpage.template"
71 destination="${config.storageRoot}/index.shtml"/>
76 we will later learn that this producer generates a single file.
79 Producers can be made to do different things for different verbs:
83 <producer name="content">
85 <verb name="new">
86 <Set key="count" value="3"/>
88 <verb name="all">
89 <Set key="count" value="5"/>
94 generator="/producer/startpage.template"
95 destination="${config.storageRoot}/index.shtml"/>
100 if a producer is called with a specific verb, first the nodes of that verb
101 are processed, and only thereafter the body: in our case, if the producer
102 <code>content</code> is called with verb <code>new</code>, first the variable <code>count</code>
104 is set to <code>3</code>, and after that, a file is generated.
108 <section><title>Node arguments</title>
110 Nodes can have arguments.
111 Arguments that amount to integer values can be direct expressions.
112 Arguments that amount to text values can be enriched with expressions between ${}.
118 <Log message="This article has the following title: ${content.title}"/>
121 <code>Log</code> has 1 mandatory argument, <code>message</code>. This argument should be text,
122 but can be enriched with expressions enclosed by ${ and }. In this example,
123 the title of an article is logged.
126 <Set key="age" value="34+22*(3+2)"/>
128 <code>Set</code> has 2 mandatory argument: <code>key</code> and <code>value</code>.
129 The key arugment is a fixed text,
130 the value argument is a direct expression, in this case of arithmetic nature.
135 <section><title>Expressions</title>
139 Expressions, either direct expressions, or expressions between ${}, can contain the following
145 <title>Expressions</title>
147 <tr><td>a string literal</td> <td><code>'hello'</code></td></tr>
148 <tr><td>a numeric literal</td> <td><code>2138</code></td></tr>
150 <tr><td>a variable reference</td> <td><code>content.title</code></td></tr>
151 <tr><td>arithmetic operators</td> <td><code> 3 + 4 *(2+5-2)</code></td></tr>
152 <tr><td>string operators</td> <td><code> 'hello' ++ ' ' ++ 'Mir'</code></td></tr>
154 <tr><td>boolean operators</td> <td><code>(content.id==3) or (content.id in (5,7,2,8) and (content.title!='hello')</code></td></tr>
159 <section><title>Node types and statements</title>
161 Here's a list of different node types that can be used inside
162 producer definitions.
163 Currently, there exists only one statement (<nodedefinition>), that
164 is declared outside producer definitions.
171 <title>Reference for producer node types and statements</title>
173 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Set</code></td></tr>
174 <tr><td>Purpose</td> <td>Alter a variable's using a free expression</td></tr>
177 <tr><td>key</td> <td>The variable</td></tr>
179 <tr><td>value</td> <td>The expression to set the variable to</td></tr>
184 <Set key="data.result" value="3 + 5 * (5-2)"/>
191 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Define</code></td></tr>
192 <tr><td>Purpose</td> <td>Alter a variable's using a string</td></tr>
196 <tr><td>key</td> <td>The variable</td></tr>
197 <tr><td>value</td> <td>The string to set the variable to</td></tr>
203 <Define key="filename" value="/var/www/${content.id}.shtml"/>
210 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>If</code></td></tr>
212 <tr><td>Purpose</td> <td>Create a conditional part of a producer</td></tr>
215 <tr><td>condition</td> <td>The expression to test</td></tr>
219 <tr><td>then</td> <td>The part to process if the expression evaluates to true</td></tr>
220 <tr><td>else</td> <td>The part to process if the expression evaluates to false</td></tr>
223 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>nodedefinition</code> (statement)</td></tr>
225 <tr><td>Purpose</td> <td>Acts as a "function" (or "macro") that can be "called" elsewhere in a producer.
226 More precisely, it is a way to define a new producer node type
227 inside the <filename>producers.xml</filename> file.
228 (check the <code>Language</code> node in that file for an example).
232 <tr><td>name</td> <td>The name of the newly created node ("function")</td></tr>
236 <tr><td>parameters</td> <td>a list describing the arguments the "function" must be given </td></tr>
237 <tr><td>definition</td> <td>the actual body of the function, containing the code that should be executed. Note that this may contain a <code><sub/></code> tag that is replaced by the child nodes of the calling node. </td></tr>
242 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Log</code></td></tr>
244 <tr><td>Purpose</td> <td>Log a message in the producer log</td></tr>
247 <tr><td>message</td> <td>The message to log</td></tr>
251 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Enumerate</code></td></tr>
252 <tr><td>Purpose</td> <td>Enumerate over the results of a query</td></tr>
255 <tr><td>key</td> <td>The variable name that receives the enumerated record</td></tr>
257 <tr><td>table</td> <td>The table that is used to enumerate over</td></tr>
258 <tr><td>selection (optional)</td> <td>The condition (where clause) of the query.</td></tr>
259 <tr><td>order (optional)</td> <td>The order in which the results of the query are enumerated.</td></tr>
260 <tr><td>skip (optional)</td> <td>The number of records to skip</td></tr>
262 <tr><td>limit (optional)</td> <td>The maximum number of records to enumerate</td></tr>
266 This node can have subnodes that will be processed for every enumerated record</td></tr>
277 <Generate generator="/producer/content.template" destination="/var/www/${content.date.formatted.yyyy}/${content.date.formatted.MM}/${content.id}.shtml"/>
286 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>List</code></td></tr>
288 <tr><td>Purpose</td> <td>Store the results of a query into a variable</td></tr>
291 <tr><td>key</td> <td>The variable name that receives the result list</td></tr>
292 <tr><td>table</td> <td>The table that is used to select from</td></tr>
294 <tr><td>selection (optional)</td> <td>The condition (where clause) of the query.</td></tr>
295 <tr><td>order (optional)</td> <td>The order in which the results of the query are put into the list.</td></tr>
296 <tr><td>skip (optional)</td> <td>The number of records to skip</td></tr>
297 <tr><td>limit (optional)</td> <td>The maximum size of the list</td></tr>
301 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Batch</code></td></tr>
302 <tr><td>Purpose</td> <td>Divide the results of a query into batches</td></tr>
306 <tr><td>key</td> <td>The variable name that receives the batch</td></tr>
307 <tr><td>infokey</td> <td>The variable name that receives meta information on the batches</td></tr>
308 <tr><td>table</td> <td>The table that is used to select from</td></tr>
309 <tr><td>batchsize</td> <td>The size of a batch (the first batch however varies in size)</td></tr>
311 <tr><td>selection (optional)</td> <td>The condition (where clause) of the query.</td></tr>
312 <tr><td>order (optional)</td> <td>The order in which the results of the query are put into the list.</td></tr>
313 <tr><td>skip (optional)</td> <td>The number of records to skip</td></tr>
314 <tr><td>process (optional)</td> <td>The maximum number of batches to process</td></tr>
316 <tr><td>minbatchsize (optional)</td> <td>The minimal size of the first batch</td></tr>
319 <tr><td>batches</td> <td>The part to process for every batch</td></tr>
320 <tr><td>batchlist</td> <td>The part to process once with the meta info</td></tr>
327 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Generate</code></td></tr>
328 <tr><td>Purpose</td> <td>Generate a page using a generator (i.e. an abstraction of a template)</td></tr>
333 <tr><td>generator</td> <td>the generator to use</td></tr>
334 <tr><td>destination</td> <td>the specification of the destination.</td></tr>
335 <tr><td>parameters</td> <td>Additional configuration info for the generator (for
336 freemarker this now only contains the wanted encoding,
337 empty for the default).</td></tr>
342 This node is used to have an actual page generated.
343 The generator parameter usually is the name of a template.
344 The destination is the file to be generated.
345 Variable references are possible in all arguments, and, especially for the
346 destination attribute, widely used.
354 <Generate generator="/producer/content.template" destination="/var/www/${content.date.formatted.yyyy}/${content.date.formatted.MM}/${content.id}.shtml"/>
361 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>GenerateMedia</code></td></tr>
362 <tr><td>Purpose</td> <td>
363 The generateMedia node instructs the media handler associated with the media to
364 "reproduce" the media. In practice this can mean generate an icon from an image,
365 writing an image from the database to the web root, or create an m3u file or so.
366 Media handling is limited at this moment, but a serious
367 redesign is planned right after 1.1
373 <tr><td>key</td> <td>FIXME???</td></tr>
377 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>DeleteFile</code></td></tr>
378 <tr><td>Purpose</td> <td>Delete a file</td></tr>
381 <tr><td>filename</td> <td>The filename of the file to delete</td></tr>
387 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>SetFileDate</code></td></tr>
388 <tr><td>Purpose</td> <td>Set a file's date</td></tr>
392 <tr><td>filename</td> <td>The filename</td></tr>
393 <tr><td>date</td> <td>The date to use</td></tr>
398 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Resource</code></td></tr>
399 <tr><td>Purpose</td> <td>Make a message resource bundle available. In other words, this defines a function that can be used in expressions to reference a bundle. </td></tr>
403 <tr><td>key</td> <td>The name of the function.</td></tr>
404 <tr><td>bundle</td> <td>The bundle to use</td></tr>
405 <tr><td>language (optional)</td> <td>The specific language to use</td></tr>
410 <Resource bundle="bundles.producer" key="lang" language="en"/>
412 This makes the english language producer bundle available
413 through the "lang()" function. One
414 can then use expressions like ${lang("page.title")} to
415 refer to a that value.
423 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Execute</code></td></tr>
424 <tr><td>Purpose</td> <td>Execute a script</td></tr>
428 <tr><td>command</td> <td>The command to execute</td></tr>
435 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>ModifyContent</code></td></tr>
436 <tr><td>Purpose</td> <td>Modify a field of an article</td></tr>
440 <tr><td>key</td> <td>The variable containing the article</td></tr>
441 <tr><td>field</td> <td>The field to modify</td></tr>
442 <tr><td>value</td> <td>The value to set the field to</td></tr>
446 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>MarkContent</code></td></tr>
447 <tr><td>Purpose</td> <td>Mark an article as produced</td></tr>
451 <tr><td>key</td> <td>The variable containing the article</td></tr>
453 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>IndexContent</code></td></tr>
454 <tr><td>Purpose</td> <td>adds/updates content to the search index (search engine)</td></tr>
458 <tr><td>key</td> <td>The variable containing the article (FIXME????)</td></tr>
459 <tr><td>pathToIndex</td> <td>(FIXME????)</td></tr>
461 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>UnIndexContent</code></td></tr>
462 <tr><td>Purpose</td> <td>removes content from the search index (search engine)</td></tr>
466 <tr><td>key</td> <td>The variable containing the article (FIXME????)</td></tr>
467 <tr><td>pathToIndex</td> <td>(FIXME????)</td></tr>
473 <section><title>How the producer framework is implemented</title>
475 <!-- <para>A Producer is a set of tasks, scripted in xml. Producers allow -->
476 <!-- mir installations to have their own actions that can be called for -->
477 <!-- instance when a new article is posted. Originally producers were -->
478 <!-- mostly used to generate pages, but they are used for a lot of -->
479 <!-- other tasks such as pulling rss feeds for the global wire on -->
480 <!-- indymedia.org. Producers are added and configured through the -->
481 <!-- <filename>producers.xml</filename> file.</para> -->
484 <para>The xml nodes contained within a <code><producer></code>
485 tag in the <filename>producers.xml</filename> file define
487 This program (or script) may contain constructs
488 such as <code>if</code> clauses, loops and variables... The program is parsed into a
489 tree of <classname>ProducerNode</classname>s (figure). The root of this tree is defined in a
490 <classname>NodedProducer</classname> (which is the only class that currently implements
491 the <classname>Producer</classname> interface). When the producer is executed, the
492 <function>produce()</function> methods of each node are recursively called, effectively
493 executing the program as it was scripted. </para>
495 <figure><title>A producer in the <filename>producer.xml</filename> file is parsed into a tree of <classname>ProducerNodes</classname></title>
498 <imagedata fileref="figures/producer-node-tree-example.eps" format="EPS"></imagedata></imageobject>
500 <imagedata fileref="figures/producer-node-tree-example.png" format="PNG"></imagedata></imageobject>