Author: rhauch
Date: 2008-09-05 10:50:20 -0400 (Fri, 05 Sep 2008)
New Revision: 499
Modified:
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java
trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna.xml
Log:
DNA-69 Note in section 1 of Using JBoss DNA should explain use of criteria for image
sequencer config path expression
https://jira.jboss.org/jira/browse/DNA-69
Added more description of the path expression and the formatting rules. The section
should be self-explanatory without having to go to the code.
Modified:
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java
===================================================================
---
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java 2008-09-04
18:58:12 UTC (rev 498)
+++
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java 2008-09-05
14:50:20 UTC (rev 499)
@@ -47,10 +47,10 @@
import org.jboss.dna.repository.observation.ObservationService;
import org.jboss.dna.repository.sequencers.SequencerConfig;
import org.jboss.dna.repository.sequencers.SequencingService;
+import org.jboss.dna.repository.util.BasicJcrExecutionContext;
import org.jboss.dna.repository.util.JcrExecutionContext;
import org.jboss.dna.repository.util.JcrTools;
import org.jboss.dna.repository.util.SessionFactory;
-import org.jboss.dna.repository.util.BasicJcrExecutionContext;
import org.jboss.dna.repository.util.SimpleSessionFactory;
/**
@@ -241,7 +241,7 @@
String desc = "Sequences image files to extract the characteristics of
the image";
String classname =
"org.jboss.dna.sequencer.images.ImageMetadataSequencer";
String[] classpath = null; // Use the current classpath
- String[] pathExpressions =
{"//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data]
=> /images/$1"};
+ String[] pathExpressions =
{"//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd)[*])/jcr:content[@jcr:data]
=> /images/$1"};
SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc,
classname, classpath, pathExpressions);
this.sequencingService.addSequencer(imageSequencerConfig);
@@ -249,7 +249,7 @@
name = "Mp3 Sequencer";
desc = "Sequences mp3 files to extract the id3 tags of the audio
file";
classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
- String[] mp3PathExpressions = {"//(*.mp3)[*]/jcr:content[@jcr:data]
=> /mp3s/$1"};
+ String[] mp3PathExpressions = {"//(*.mp3[*])/jcr:content[@jcr:data]
=> /mp3s/$1"};
SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc,
classname, classpath, mp3PathExpressions);
this.sequencingService.addSequencer(mp3SequencerConfig);
Modified: trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna.xml 2008-09-04
18:58:12 UTC (rev 498)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna.xml 2008-09-05
14:50:20 UTC (rev 499)
@@ -108,7 +108,7 @@
String desc = "Sequences image files to extract the characteristics of the
image";
String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
String[] classpath = null; // Use the current classpath
-String[] pathExpressions =
{"//(*.(jpg|jpeg|gif|bmp|pcx|png))[*]/jcr:content[@jcr:data] =>
/images/$1"};
+String[] pathExpressions =
{"//(*.(jpg|jpeg|gif|bmp|pcx|png)[*])/jcr:content[@jcr:data] =>
/images/$1"};
SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname,
classpath, pathExpressions);
sequencingService.addSequencer(imageSequencerConfig);
@@ -116,12 +116,12 @@
name = "Mp3 Sequencer";
desc = "Sequences mp3 files to extract the id3 tags of the audio file";
classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
-String[] mp3PathExpressions = {"//(*.mp3)[*]/jcr:content[@jcr:data] =>
/mp3s/$1"};
+String[] mp3PathExpressions = {"//(*.mp3[*])/jcr:content[@jcr:data] =>
/mp3s/$1"};
SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc, classname,
classpath, mp3PathExpressions);
sequencingService.addSequencer(mp3SequencerConfig);
]]></programlisting>
- <para>This is pretty self-explanatory, except for the
<code>classpath</code> and <code>pathExpression</code>
parameters.
+ <para>This code fragment is pretty self-explanatory, except for the
<code>classpath</code> and <code>pathExpression</code>
parameters.
The classpath parameter defines the classpath that is passed to the class loader
factory mentioned above.
Our sequencer is on the classpath, so we can simply use
<code>null</code> here.</para>
<para>The path expression is more complicated. Sequencer path expressions are
used by the sequencing service to
@@ -129,51 +129,88 @@
criteria and an output expression:</para>
<programlisting><![CDATA[ inputPath => outputPath
]]></programlisting>
<para>The <emphasis>inputPath</emphasis> part defines an expression
for the path that is to change and that should be sequenced.
- Input paths must match node names (including same-name-sibling indexes), and can
use wildcards in the names and/or indexes.
- Wildcards include:
- <itemizedlist>
- <listitem>
- <para>"<code>//</code>" mean any sequence of nodes,
regardless of what their names are</para>
- </listitem>
- <listitem>
- <para>"<code>*</code>" means a node with any name and
any same-name-sibling index</para>
- </listitem>
- </itemizedlist>
- </para>
- <para>The <emphasis>inputPath</emphasis> part defines an expression
for the path that is to change and that should be sequenced.
- Input paths must match node names (including same-name-sibling indexes), and can
use wildcards in the names and/or indexes.
- The characters "<code>//</code>" mean any sequence of nodes
(regardless of what their names are), and "<code>*</code>"
- means a node with any
-
-
-
-
- while
- the <emphasis>outputPath</emphasis> part defines the location where the
content generated by the sequencer should be stored.</para>
- <para>Here's a simple example:</para>
- <programlisting><![CDATA[ /a/b/c@title => /d/e/f
]]></programlisting>
- <para>Here, the <code>/a/b/c@title</code> is the selection criteria
that applies when the <code>/a/b/c</code> node has a
<code>title</code> property
- that is added or changed. When the selection criteria matches a change event, the
sequencer will be run
- and any generated output will be inserted into the repository described by the
output expression. In this example,
- the generated output would be placed at the <code>/d/e/f</code>
node.</para>
- <note>
- <para>Sequencer path expressions can be fairly complex and may use wildcards,
specificy same-name sibling indexes,
- provide optional and choice elements, and may capture parts of the selection
criteria for use in the output expression.
- The path expression used in the image sequencer configuration example above shows
a more complex example:</para>
- <programlisting><![CDATA[
//(*.(jpg|jpeg|gif|bmp|pcx|png))[*]/jcr:content[@jcr:data] => /images/$1
]]></programlisting>
- <para>This uses "//" to select any node at any level in the
repository whose name ends with "." and one of the extensions (e.g.,
".jpg", ".jpeg", etc.)
- and that has a child node named "jcr:content" that has a
"jcr:data" property. It also selects the file name
- as the first capture group (the first set of parentheses) for use in the output
expression.
- In this example, any sequencer output is placed on a node with that same file
name under the "/images" node.</para>
- <para>Other things are possible, too. For example, the name of the
repository/workspace (as used by the <code>SessionFactory</code>)
- may be specified at the beginning of the select criteria and/or the output
expression. This means it's possible to place
- the sequencer output in a different repository than the node being
sequenced.</para>
- <para>For more detail about sequencer path expressions, see the
<code>org.jboss.dna.repository.sequencer.SequencerPathExpression</code>
- class and the corresponding
<code>org.jboss.dna.repository.sequencer.SequencerPathExpressionTest</code>
test case.</para>
- </note>
- <para>After the service is started, it is ready to start reacting to changes in
the repository. But it first
- must be wired to the repositories using a listener. This is accomplished using the
<code>ObservationService</code>
- described in the <link linkend="observation_service">next
section</link>.</para>
+ Input paths consist of '<code>/</code>' separated segments, where
each segment represents a pattern for a single node's
+ name (including the same-name-sibling indexes) and
'<code>@</code>' signifies a property name.</para>
+ <para>Before getting into the details, let's look at some simple
examples:</para>
+ <table frame='all'>
+ <title>Simple Input Path Examples</title>
+ <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Input Path</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row><entry>/a/b</entry><entry>Match node
"<code>b</code>" that is a child of the top level node
"<code>a</code>". Neither node
+ may have any same-name-sibilings.</entry></row>
+ <row><entry>/a/*</entry><entry>Match any child node of the
top level node "<code>a</code>".</entry></row>
+ <row><entry>/a/*.txt</entry><entry>Match any child node of
the top level node "<code>a</code>" that also has a name ending in
"<code>.txt</code>".</entry></row>
+ <row><entry>/a/*.txt</entry><entry>Match any child node of
the top level node "<code>a</code>" that also has a name ending in
"<code>.txt</code>".</entry></row>
+ <row><entry>/a/b@c</entry><entry>Match the property
"<code>c</code>" of node
"<code>/a/b</code>".</entry></row>
+ <row><entry>/a/b[2]</entry><entry>The second child named
"<code>b</code>" below the top level node
"<code>a</code>".</entry></row>
+ <row><entry>/a/b[2,3,4]</entry><entry>The second, third or
fourth child named "<code>b</code>" below the top level node
"<code>a</code>".</entry></row>
+ <row><entry>/a/b[*]</entry><entry>Any (and every) child
named "<code>b</code>" below the top level node
"<code>a</code>".</entry></row>
+ <row><entry>//a/b</entry><entry>Any node named
"<code>b</code>" that exists below a node named
"<code>a</code>", regardless
+ of where node "<code>a</code>" occurs. Again, neither
node may have any same-name-sibilings.</entry></row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>With these simple examples, you can probably discern the most important
rules. First, the '<code>*</code>' is a wildcard character
+ that matches any character or sequence of characters in a node's name (or index
if appearing in between square brackets), and
+ can be used in conjunction with other characters (e.g.,
"<code>*.txt</code>").</para>
+ <para>Second, square brackets (i.e., '<code>[</code>' and
'<code>]</code>') are used to match a node's same-name-sibiling
index.
+ You can put a single non-negative number or a comma-separated list of non-negative
numbers. Use '0' to match a node that has no
+ same-name-sibilings, or any positive number to match the specific
same-name-sibling.</para>
+ <para>Third, combining two delimiters (e.g.,
"<code>//</code>") matches any sequence of nodes, regardless of what
their names are
+ or how many nodes. Often used with other patterns to identify nodes at any level
matching other patterns.
+ Three or more sequential slash characters are treated as two.</para>
+ <para>Many input paths can be created using just these simple rules. However,
input paths can be more complicated. Here are some
+ more examples:</para>
+ <table frame='all'>
+ <title>More Complex Input Path Examples</title>
+ <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Input Path</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row><entry>/a/(b|c|d)</entry><entry>Match children of the
top level node "<code>a</code>" that are named
"<code>a</code>",
+ "<code>b</code>" or
"<code>c</code>". None of the nodes may have same-name-sibling
indexes.</entry></row>
+ <row><entry>/a/b[c/d]</entry><entry>Match node
"<code>b</code>" child of the top level node
"<code>a</code>", when node
+ "<code>b</code>" has a child named
"<code>c</code>", and "<code>c</code>" has a
child named "<code>d</code>".
+ Node "<code>b</code>" is the selected node, while nodes
"<code>b</code>" and "<code>b</code>" are used
as criteria but are not
+ selected.</entry></row>
+ <row><entry>/a(/(b|c|d|)/e)[f/g/@something]</entry><entry>Match
node "<code>/a/b/e</code>",
"<code>/a/c/e</code>", "<code>/a/d/e</code>",
+ or "<code>/a/e</code>" when they also have a child
"<code>f</code>" that itself has a child
"<code>g</code>" with property
+ "<code>something</code>". None of the nodes may have
same-name-sibling indexes.</entry></row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>These examples show a few more advanced rules. Parentheses (i.e.,
'<code>(</code>' and '<code>)</code>') can be
used
+ to define a set of options for names, as shown in the first and third rules.
Whatever part of the selected node's path
+ appears between the parentheses is captured for use within the output path. Thus,
the first input path in the previous table
+ would match node "<code>/a/b</code>", and "b" would
be captured and could be used within the output path using
"<code>$1</code>",
+ where the number used in the output path identifies the parentheses.</para>
+ <para>Square brackets can also be used to specify criteria on a node's
properties or children. Whatever appears in between the square
+ brackets does not appear in the selected node.</para>
+ <para>Let's go back to the previous code fragment and look at the first
path expression:</para>
+ <programlisting><![CDATA[
//(*.(jpg|jpeg|gif|bmp|pcx|png)[*])/jcr:content[@jcr:data] => /images/$1
]]></programlisting>
+ <para>This matches a node named
"<code>jcr:content</code>" with property
"<code>jcr:data</code>" but no siblings with the same name,
+ and that is a child of a node whose name ends with
"<code>.jpg</code>", "<code>.jpeg</code>",
"<code>.gif</code>", "<code>.bmp</code>",
"<code>.pcx</code>",
+ or "<code>.png</code>" that may have any same-name-sibling
index. These nodes can appear at any level in the repository.
+ Note how the input path capture the filename (the segment containing the file
extension), including any same-name-sibling index.
+ This filename is then used in the output path, which is where the sequenced content
is placed.</para>
+ <para>Now that we've covered path expressions, let's get back to the
<code>SequencingService</code>.
+ After the service is started, it is ready to start reacting to changes in the
repository. But it first
+ must be wired to the repositories using a listener. This is accomplished using
the <code>ObservationService</code>
+ described in the <link linkend="observation_service">next
section</link>.</para>
</sect1>
<sect1 id="observation_service">
<title>Configuring the Observation Service</title>