<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ ModeShape (http://www.modeshape.org)
  ~
  ~ See the COPYRIGHT.txt file distributed with this work for information
  ~ regarding copyright ownership.  Some portions may be licensed
  ~ to Red Hat, Inc. under one or more contributor license agreements.
  ~ See the AUTHORS.txt file in the distribution for a full listing of 
  ~ individual contributors.
  ~
  ~ ModeShape is free software. Unless otherwise indicated, all code in ModeShape
  ~ is licensed to you under the terms of the GNU Lesser General Public License as
  ~ published by the Free Software Foundation; either version 2.1 of
  ~ the License, or (at your option) any later version.
  ~
  ~ ModeShape is distributed in the hope that it will be useful,
  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  ~ or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
  ~ for more details.
  ~
  ~ You should have received a copy of the GNU Lesser General Public License
  ~ along with this distribution; if not, write to:
  ~ Free Software Foundation, Inc.
  ~ 51 Franklin Street, Fifth Floor
  ~ Boston, MA  02110-1301  USA
  -->
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"	[
<!ENTITY % CustomDTD SYSTEM "../../custom.dtd">
%CustomDTD;
]>
<chapter id="text-sequencer">
  <title>Text Sequencers</title>
     <para>
		The text sequencers extract data from text streams.  There are separate sequencers for character-delimited sequencing and fixed
		width sequencing, but both treat the incoming text stream as a series of rows (separated by line-terminators, as defined in 
		&BufferedReader;.readLine() with each row consisting of one or more columns.  As noted above, each text sequencer provides its 
		own mechanism for splitting the row into columns. 
     </para>
	<para>
		The &AbstractTextSequencer; class provides a number of JavaBean properties that are common to both of the concrete text sequencer classes:
	</para>
	<table frame='all'>
		<title>&AbstractTextSequencer; properties</title>
		<tgroup cols='2' align='left' colsep='1' rowsep='1'>
      <colspec colname='c1' colwidth="1*"/>
      <colspec colname='c2' colwidth="1*"/>
			<thead>
				<row>
		  		<entry>Property</entry>
		  		<entry>Description</entry>
				</row>
			</thead>
			<tbody>
				<row>
					<entry>commentMarker</entry>
					<entry>
						Optional property that, if set, indicates that any line beginning with <emphasis>exactly this string</emphasis> should 
						be treated as a comment and should not be processed further.  If this value is null, then all lines will be sequenced.  
						The default value for this property is null.
					</entry>
				</row>
				<row>
					<entry>maximumLinesToRead</entry>
					<entry>
						Optional property that, if set, limits the number of lines that will be read during sequencing.  Additional lines will be
						ignored.  If this value is non-positive, all lines will be read and sequenced.  Comment lines are not counted towards this total.
						The default value of this property is -1 (indicating that all lines should be read and sequenced).
					</entry>
				</row>
				<row>
					<entry>rowFactoryClassName</entry>
					<entry>
						Optional property that, if set, provides the name of a class that provides a custom implementation of the &RowFactory; interface.  
						This class must have a no-argument, public constructor.  If set, an instance of this class will be created each time that the sequencer
						sequences an input stream and will be used to provide the output structure of the graph.  If this property is set to null,
						a default implementation will be used.  The default value of this property is null.  
					</entry>
				</row>
			</tbody>
		</tgroup>
	</table>
	<para>
		The default row factory creates one node in the output location for each row sequenced from the source and adds each column with the row as a
		child node of the row node.  The output graph takes the following form (all nodes have primary type <code>nt:unstructured</code>:  
	</para>
	<programlisting>
 &lt;graph root jcr:mixinTypes = mode:derived, 
                mode:derivedAt="2011-05-13T13:12:03.925Z", 
                mode:derivedFrom="/files/foo.dat"&gt;
     + text:row[1]
     |   + text:column[1] (jcr:mixinTypes = text:column, text:data = &lt;column1 data&gt;)
     |   + ...
     |   + text:column[n] (jcr:mixinTypes = text:column, text:data = &lt;columnN data&gt;)
     + ...
     + text:row[m]
         + text:column[1] (jcr:mixinTypes = text:column, text:data = &lt;column1 data&gt;)
         + ...
         + text:column[n] (jcr:mixinTypes = text:column, text:data = &lt;columnN data&gt;)
	
	</programlisting>
	<sect1>
        <title>Delimited Text Sequencer</title>
	    <para>
	    	The &DelimitedTextSequencer; splits rows into columns based on a regular expression pattern.  Although the default pattern is a comma,
	    	any regular expression can be provided allowing for more sophisticated splitting patterns.
	    </para>
		<para>
			The &DelimitedTextSequencer; class provides an additional JavaBean property to override the default regular expression pattern:
		</para>
		<table frame='all'>
			<title>&DelimitedTextSequencer; properties</title>
			<tgroup cols='2' align='left' colsep='1' rowsep='1'>
	      <colspec colname='c1' colwidth="1*"/>
	      <colspec colname='c2' colwidth="1*"/>
				<thead>
					<row>
			  		<entry>Property</entry>
			  		<entry>Description</entry>
					</row>
				</thead>
				<tbody>
					<row>
						<entry>splitPattern</entry>
						<entry>
							Optional property that, if set, sets the regular expression pattern that is used to split each row into columns.  This property
							may not be set to null and defaults to ",".
						</entry>
					</row>
				</tbody>
			</tgroup>
		</table>
	    <para>
	        To use this sequencer, simply include the <code>modeshape-sequencer-text</code> JAR
	        in your application and configure the &JcrConfiguration; to use this sequencer using something similar to:
	    </para>
	   	<programlisting language="JAVA" role="JAVA"><![CDATA[
JcrConfiguration config = ...

config.sequencer("Delimited Text Sequencer")
      .usingClass("org.modeshape.sequencer.text.DelimitedTextSequencer")
      .loadedFromClasspath()
      .setDescription("Sequences delimited files to extract values")
      .sequencingFrom("//(*.(txt)[*])/jcr:content[@jcr:data]")
      .setProperty("splitPattern", "|")
      .andOutputtingTo("/txt/$1"); 
]]></programlisting>
	</sect1>
	<sect1>
        <title>Fixed Width Text Sequencer</title>
	    <para>
	    	The &FixedWidthTextSequencer; splits rows into columns based on predefined positions.  The default setting is to have a single
	    	column per row.  It also provides an additional JavaBean property to override the default start positions for each column.
		</para>
		<table frame='all'>
			<title>&FixedWidthTextSequencer; properties</title>
			<tgroup cols='2' align='left' colsep='1' rowsep='1'>
	      <colspec colname='c1' colwidth="1*"/>
	      <colspec colname='c2' colwidth="1*"/>
				<thead>
					<row>
			  		<entry>Property</entry>
			  		<entry>Description</entry>
					</row>
				</thead>
				<tbody>
					<row>
						<entry>columnStartPositions</entry>
						<entry>
							Optional property that, if set, provides the start position of each column after the first.  The start
							positions are concatenated into a single, comma-delimited string.  The default value is the empty string
							(implying that each row should be treated as a single column).  This property may not be set to null.  There
							is an implicit column start position of 0 that never needs to be specified.
						</entry>
					</row>
				</tbody>
			</tgroup>
		</table>
	    <para>
	        To use this sequencer, simply include the <code>modeshape-sequencer-text</code> JAR
	        in your application and configure the &JcrConfiguration; to use this sequencer using something similar to:
	    </para>
	   	<programlisting language="JAVA" role="JAVA"><![CDATA[
JcrConfiguration config = ...

config.sequencer("Fixed Width Text Sequencer")
      .usingClass("org.modeshape.sequencer.text.FixedWidthTextSequencer")
      .loadedFromClasspath()
      .setDescription("Sequences fixed width files to extract values")
      .sequencingFrom("//(*.(txt)[*])/jcr:content[@jcr:data]")
      .setProperty("columnStartPositions", "3,6,15")
      .andOutputtingTo("/txt/$1"); 
]]></programlisting>
	</sect1>
</chapter>
