1 <chapter id="introduction">
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 <tr><td>a string literal</td> <td><code>'hello'</code></td></tr>
146 <tr><td>a numeric literal</td> <td><code>2138</code></td></tr>
148 <tr><td>a variable reference</td> <td><code>content.title</code></td></tr>
149 <tr><td>arithmetic operators</td> <td><code> 3 + 4 *(2+5-2)</code></td></tr>
150 <tr><td>string operators</td> <td><code> 'hello' ++ ' ' ++ 'Mir'</code></td></tr>
152 <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>
157 <section><title>Node types and statements</title>
159 Here's a list of different node types that can be used inside
160 producer definitions.
161 Currently, there exists only one statement (<nodedefinition>), that
162 is declared outside producer definitions.
170 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Set</code></td></tr>
171 <tr><td>Purpose</td> <td>Alter a variable's using a free expression</td></tr>
174 <tr><td>key</td> <td>The variable</td></tr>
176 <tr><td>value</td> <td>The expression to set the variable to</td></tr>
181 <Set key="data.result" value="3 + 5 * (5-2)"/>
188 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Define</code></td></tr>
189 <tr><td>Purpose</td> <td>Alter a variable's using a string</td></tr>
193 <tr><td>key</td> <td>The variable</td></tr>
194 <tr><td>value</td> <td>The string to set the variable to</td></tr>
200 <Define key="filename" value="/var/www/${content.id}.shtml"/>
207 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>If</code></td></tr>
209 <tr><td>Purpose</td> <td>Create a conditional part of a producer</td></tr>
212 <tr><td>condition</td> <td>The expression to test</td></tr>
216 <tr><td>then</td> <td>The part to process if the expression evaluates to true</td></tr>
217 <tr><td>else</td> <td>The part to process if the expression evaluates to false</td></tr>
220 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>nodedefinition</code> (statement)</td></tr>
222 <tr><td>Purpose</td> <td>Acts as a "function" (or "macro") that can be "called" elsewhere in a producer.
223 More precisely, it is a way to define a new producer node type
224 inside the <filename>producers.xml</filename> file.
225 (check the <code>Language</code> node in that file for an example).
229 <tr><td>name</td> <td>The name of the newly created node ("function")</td></tr>
233 <tr><td>parameters</td> <td>a list describing the arguments the "function" must be given </td></tr>
234 <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>
239 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Log</code></td></tr>
241 <tr><td>Purpose</td> <td>Log a message in the producer log</td></tr>
244 <tr><td>message</td> <td>The message to log</td></tr>
248 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Enumerate</code></td></tr>
249 <tr><td>Purpose</td> <td>Enumerate over the results of a query</td></tr>
252 <tr><td>key</td> <td>The variable name that receives the enumerated record</td></tr>
254 <tr><td>table</td> <td>The table that is used to enumerate over</td></tr>
255 <tr><td>selection (optional)</td> <td>The condition (where clause) of the query.</td></tr>
256 <tr><td>order (optional)</td> <td>The order in which the results of the query are enumerated.</td></tr>
257 <tr><td>skip (optional)</td> <td>The number of records to skip</td></tr>
259 <tr><td>limit (optional)</td> <td>The maximum number of records to enumerate</td></tr>
263 This node can have subnodes that will be processed for every enumerated record</td></tr>
274 <Generate generator="/producer/content.template" destination="/var/www/${content.date.formatted.yyyy}/${content.date.formatted.MM}/${content.id}.shtml"/>
283 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>List</code></td></tr>
285 <tr><td>Purpose</td> <td>Store the results of a query into a variable</td></tr>
288 <tr><td>key</td> <td>The variable name that receives the result list</td></tr>
289 <tr><td>table</td> <td>The table that is used to select from</td></tr>
291 <tr><td>selection (optional)</td> <td>The condition (where clause) of the query.</td></tr>
292 <tr><td>order (optional)</td> <td>The order in which the results of the query are put into the list.</td></tr>
293 <tr><td>skip (optional)</td> <td>The number of records to skip</td></tr>
294 <tr><td>limit (optional)</td> <td>The maximum size of the list</td></tr>
298 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Batch</code></td></tr>
299 <tr><td>Purpose</td> <td>Divide the results of a query into batches</td></tr>
303 <tr><td>key</td> <td>The variable name that receives the batch</td></tr>
304 <tr><td>infokey</td> <td>The variable name that receives meta information on the batches</td></tr>
305 <tr><td>table</td> <td>The table that is used to select from</td></tr>
306 <tr><td>batchsize</td> <td>The size of a batch (the first batch however varies in size)</td></tr>
308 <tr><td>selection (optional)</td> <td>The condition (where clause) of the query.</td></tr>
309 <tr><td>order (optional)</td> <td>The order in which the results of the query are put into the list.</td></tr>
310 <tr><td>skip (optional)</td> <td>The number of records to skip</td></tr>
311 <tr><td>process (optional)</td> <td>The maximum number of batches to process</td></tr>
313 <tr><td>minbatchsize (optional)</td> <td>The minimal size of the first batch</td></tr>
316 <tr><td>batches</td> <td>The part to process for every batch</td></tr>
317 <tr><td>batchlist</td> <td>The part to process once with the meta info</td></tr>
324 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Generate</code></td></tr>
325 <tr><td>Purpose</td> <td>Generate a page using a generator (i.e. an abstraction of a template)</td></tr>
330 <tr><td>generator</td> <td>the generator to use</td></tr>
331 <tr><td>destination</td> <td>the specification of the destination.</td></tr>
332 <tr><td>parameters</td> <td>Additional configuration info for the generator (for
333 freemarker this now only contains the wanted encoding,
334 empty for the default).</td></tr>
339 This node is used to have an actual page generated.
340 The generator parameter usually is the name of a template.
341 The destination is the file to be generated.
342 Variable references are possible in all arguments, and, especially for the
343 destination attribute, widely used.
351 <Generate generator="/producer/content.template" destination="/var/www/${content.date.formatted.yyyy}/${content.date.formatted.MM}/${content.id}.shtml"/>
358 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>GenerateMedia</code></td></tr>
359 <tr><td>Purpose</td> <td>
360 The generateMedia node instructs the media handler associated with the media to
361 "reproduce" the media. In practice this can mean generate an icon from an image,
362 writing an image from the database to the web root, or create an m3u file or so.
363 Media handling is limited at this moment, but a serious
364 redesign is planned right after 1.1
370 <tr><td>key</td> <td>FIXME???</td></tr>
374 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>DeleteFile</code></td></tr>
375 <tr><td>Purpose</td> <td>Delete a file</td></tr>
378 <tr><td>filename</td> <td>The filename of the file to delete</td></tr>
384 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>SetFileDate</code></td></tr>
385 <tr><td>Purpose</td> <td>Set a file's date</td></tr>
389 <tr><td>filename</td> <td>The filename</td></tr>
390 <tr><td>date</td> <td>The date to use</td></tr>
395 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Resource</code></td></tr>
396 <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>
400 <tr><td>key</td> <td>The name of the function.</td></tr>
401 <tr><td>bundle</td> <td>The bundle to use</td></tr>
402 <tr><td>language (optional)</td> <td>The specific language to use</td></tr>
407 <Resource bundle="bundles.producer" key="lang" language="en"/>
409 This makes the english language producer bundle available
410 through the "lang()" function. One
411 can then use expressions like ${lang("page.title")} to
412 refer to a that value.
420 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>Execute</code></td></tr>
421 <tr><td>Purpose</td> <td>Execute a script</td></tr>
425 <tr><td>command</td> <td>The command to execute</td></tr>
432 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>ModifyContent</code></td></tr>
433 <tr><td>Purpose</td> <td>Modify a field of an article</td></tr>
437 <tr><td>key</td> <td>The variable containing the article</td></tr>
438 <tr><td>field</td> <td>The field to modify</td></tr>
439 <tr><td>value</td> <td>The value to set the field to</td></tr>
443 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>MarkContent</code></td></tr>
444 <tr><td>Purpose</td> <td>Mark an article as produced</td></tr>
448 <tr><td>key</td> <td>The variable containing the article</td></tr>
450 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>IndexContent</code></td></tr>
451 <tr><td>Purpose</td> <td>adds/updates content to the search index (search engine)</td></tr>
455 <tr><td>key</td> <td>The variable containing the article (FIXME????)</td></tr>
456 <tr><td>pathToIndex</td> <td>(FIXME????)</td></tr>
458 <tr><td>Name</td> <td bgcolor="#eea8a8"><code>UnIndexContent</code></td></tr>
459 <tr><td>Purpose</td> <td>removes content from the search index (search engine)</td></tr>
463 <tr><td>key</td> <td>The variable containing the article (FIXME????)</td></tr>
464 <tr><td>pathToIndex</td> <td>(FIXME????)</td></tr>
470 <section><title>How the producer framework is implemented</title>
472 <!-- <para>A Producer is a set of tasks, scripted in xml. Producers allow -->
473 <!-- mir installations to have their own actions that can be called for -->
474 <!-- instance when a new article is posted. Originally producers were -->
475 <!-- mostly used to generate pages, but they are used for a lot of -->
476 <!-- other tasks such as pulling rss feeds for the global wire on -->
477 <!-- indymedia.org. Producers are added and configured through the -->
478 <!-- <filename>producers.xml</filename> file.</para> -->
481 <para>The xml nodes contained within a <code><producer></code>
482 tag in the <filename>producers.xml</filename> file define
484 This program (or script) may contain constructs
485 such as <code>if</code> clauses, loops and variables... The program is parsed into a
486 tree of <classname>ProducerNode</classname>s (figure). The root of this tree is defined in a
487 <classname>NodedProducer</classname> (which is the only class that currently implements
488 the <classname>Producer</classname> interface). When the producer is executed, the
489 <function>produce()</function> methods of each node are recursively called, effectively
490 executing the program as it was scripted. </para>
492 <figure><title>A producer in the <filename>producer.xml</filename> file is parsed into a tree of <classname>ProducerNodes</classname></title>
495 <imagedata fileref="figures/producer-node-tree-example.eps" format="EPS"></imagedata></imageobject>
497 <imagedata fileref="figures/producer-node-tree-example.png" format="PNG"></imagedata></imageobject>