svn commit: r1243911 - in /cocoon/cocoon3/trunk/cocoon-optional/src: main/java/org/apache/cocoon/optional/pipeline/components/sax/csv/ main/java/org/apache/cocoon/pipeline/components/parameters/ main/resources/META-INF/cocoon/spring-optional/ test/java...

[email protected]
Newsgroups gmane.text.xml.cocoon.cvs
Message-ID <[email protected]>
Author: thorsten
Date: Tue Feb 14 13:15:59 2012
New Revision: 1243911

URL: http://svn.apache.org/viewvc?rev=1243911&view=rev
Log:
COCOON3-90
Migrating CSVGenerator fom 2.2 to c3.
Extending the generator to work as well with string input and not only with url.
Adding basic test case.

Added:
    cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/csv/
    cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/csv/CSVGenerator.java
    cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/csv/
    cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/csv/CSVGeneratorTest.java
Modified:
    cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/pipeline/components/parameters/Parameters.java
    cocoon/cocoon3/trunk/cocoon-optional/src/main/resources/META-INF/cocoon/spring-optional/cocoon-optional-generators.xml

Added: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/csv/CSVGenerator.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/csv/CSVGenerator.java?rev=1243911&view=auto
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/csv/CSVGenerator.java (added)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/csv/CSVGenerator.java Tue Feb 14 13:15:59 2012
@@ -0,0 +1,534 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.optional.pipeline.components.sax.csv;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cocoon.pipeline.components.parameters.Parameters;
+import org.apache.cocoon.sax.AbstractSAXGenerator;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * <p>
+ * A simple parser converting a Comma Separated Values (CSV) file into XML.
+ * </p>
+ * 
+ * <p>
+ * This parser is controlled by the following sitemap parameters:
+ * </p>
+ * 
+ * <ul>
+ * <li>
+ * <b>process-headers</b>: whether the first line in the CSV is considered to be
+ * the header defining column names (the resulting output will be different if
+ * this is <i>true</i> or <i>false</i> (default: <i>false</i>).</li>
+ * <li>
+ * <b>max-records</b>: the maximum number of records to read (default: <i>-1</i>
+ * read all records).</li>
+ * <li>
+ * <b>encoding</b>: the character encoding (UTF-8, ISO8859-1, ...) used to
+ * interpret the input CSV source file (default: <i>system default</i>).</li>
+ * <li>
+ * <b>separator</b>: the field-separator character in the CSV file (comma, tab,
+ * ...) (default: <i>,</i> <small>comma</small>).</li>
+ * <li>
+ * <b>escape</b>: the character used to escape fields, or part of them, in the
+ * CSV file (default: <i>"</i> <small>quote</small>).</li>
+ * <li>
+ * <b>buffer-size</b>: the size of the buffer used for reading the source CSV
+ * file (default: <i>4096 bytes</i>).</li>
+ * </ul>
+ * 
+ * <p>
+ * The generated output will look something like the following:
+ * </p>
+ * 
+ * <pre>
+ * &lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
+ * &lt;csv:document xmlns:csv="http://apache.org/cocoon/csv/1.0"&gt;
+ *   &lt;csv:header&gt;
+ *     &lt;csv:column number="1"&gt;Column A&lt;/csv:column&gt;
+ *     &lt;csv:column number="2"&gt;Column B&lt;/csv:column&gt;
+ *     &lt;csv:column number="3"&gt;Column C&lt;/csv:column&gt;
+ *   &lt;/csv:header&gt;
+ *   &lt;csv:record number="1"&gt;
+ *     &lt;csv:field number="1" column="Column A"&gt;Field A1&lt;/csv:field&gt;
+ *     &lt;csv:field number="2" column="Column B"&gt;Field B1&lt;/csv:field&gt;
+ *     &lt;csv:field number="3" column="Column C"&gt;Field C1&lt;/csv:field&gt;
+ *   &lt;/csv:record&gt;
+ *   &lt;csv:record number="2"&gt;
+ *     &lt;csv:field number="1" column="Column A"&gt;Field A2&lt;/csv:field&gt;
+ *     &lt;csv:field number="2" column="Column B"&gt;Field B2&lt;/csv:field&gt;
+ *     &lt;csv:field number="3" column="Column C"&gt;Field C2&lt;/csv:field&gt;
+ *   &lt;/csv:record&gt;
+ * &lt;/csv:document&gt;
+ * </pre>
+ * 
+ * <p>
+ * Note that this generator has been thoroughly tested with CSV files generated
+ * by <a href="http://office.microsoft.com/" target="_new">Microsoft Excel</a>.
+ * Unfortunately no official CSV specification has ever been published by any
+ * standard body, so the interpretation of the format might be slightly
+ * different in cases.
+ * </p>
+ */
+public class CSVGenerator extends AbstractSAXGenerator {// implements
+                                                        // CachingPipelineComponent
+
+    /**
+     * <p>
+     * The namespace URI of XML generated by this instance.
+     * </p>
+     */
+    public static final String NAMESPACE_URI = "http://apache.org/cocoon/csv/1.0";
+    /**
+     * <p>
+     * The namespace prefix of XML generated by this instance.
+     * </p>
+     */
+    public static final String NAMESPACE_PREFIX = "csv";
+
+    /**
+     * <p>
+     * The default encoding configured in the Java VM.
+     * </p>
+     */
+    private static final String DEFAULT_ENCODING = new InputStreamReader(
+            new ByteArrayInputStream(new byte[0])).getEncoding();
+    /**
+     * <p>
+     * The default field separator character.
+     * </p>
+     */
+    private static final String DEFAULT_SEPARATOR = ",";
+    /**
+     * <p>
+     * The default field separator character.
+     * </p>
+     */
+    private static final String DEFAULT_ESCAPE = "\"";
+    /**
+     * <p>
+     * The default field separator character.
+     * </p>
+     */
+    private static final int DEFAULT_BUFFER_SIZE = 4096;
+    private static final int UNLIMITED_MAXRECORDS = -1;
+    /**
+     * <p>
+     * A string used for indenting.
+     * </p>
+     */
+    private static final char INDENT_STRING[] = "\n          ".toCharArray();
+
+    /**
+     * <p>
+     * The encoding used to read the CSV resource from a stream.
+     * </p>
+     */
+    private String encoding = DEFAULT_ENCODING;
+    /**
+     * <p>
+     * The character used to separate fields.
+     * </p>
+     */
+    private char separator = DEFAULT_SEPARATOR.charAt(0);
+    /**
+     * <p>
+     * The character used to initiate and terminate esacaped sequences.
+     * </p>
+     */
+    private char escape = DEFAULT_ESCAPE.charAt(0);
+    /**
+     * <p>
+     * The size of the buffer used to read the input.
+     * </p>
+     */
+    private int buffersize = DEFAULT_BUFFER_SIZE;
+    /**
+     * <p>
+     * The current field (column) number in the current record.
+     * </p>
+     */
+    private int fieldnumber = 1;
+    /**
+     * <p>
+     * The current record (line) number in the current CSV.
+     * </p>
+     */
+    private int recordnumber = 1;
+    /**
+     * <p>
+     * The maximum number of records to read (-1 = read all records)
+     * </p>
+     */
+    private int maxrecords;
+    /**
+     * <p>
+     * A flag indicating whether the &lt;record&gt; tag was opened.
+     * </p>
+     */
+    private boolean openrecord = false;
+    /**
+     * <p>
+     * The character buffer for the current field.
+     * </p>
+     */
+    private CharArrayWriter buffer = null;
+    /**
+     * <p>
+     * A map of all known columns or null if no headers are processed.
+     * </p>
+     */
+    private Map columns = null;
+    private URL url;
+    private String sourceString;
+
+    /**
+     * <p>
+     * Create a new {@link CSVGenerator} instance.
+     * </p>
+     */
+    public CSVGenerator() {
+        super();
+    }
+
+    public CSVGenerator(String csv) {
+        super();
+        this.sourceString = csv;
+    }
+
+    public void recycle() {
+        this.encoding = DEFAULT_ENCODING;
+        this.separator = DEFAULT_SEPARATOR.charAt(0);
+        this.escape = DEFAULT_ESCAPE.charAt(0);
+        this.buffersize = DEFAULT_BUFFER_SIZE;
+        this.buffer = null;
+        this.columns = null;
+        this.recordnumber = 1;
+        this.fieldnumber = 1;
+        this.openrecord = false;
+    }
+
+    @Override
+    public void setConfiguration(
+            final Map<String, ? extends Object> configuration) {
+        final Parameters parameters = new Parameters(configuration);
+        boolean header = parameters.getParameterAsBoolean("process-headers",
+                false);
+        this.url = (URL) configuration.get("source");
+
+        this.encoding = (String) parameters.getParameter("encoding",
+                DEFAULT_ENCODING);
+        this.separator = ((String) parameters.getParameter("separator",
+                DEFAULT_SEPARATOR)).charAt(0);
+        this.escape = ((String) parameters.getParameter("escape",
+                DEFAULT_ESCAPE)).charAt(0);
+        this.buffersize = parameters.getAsInteger("buffer-size",
+                DEFAULT_BUFFER_SIZE);
+        this.maxrecords = parameters.getAsInteger("max-records",
+                UNLIMITED_MAXRECORDS);
+        this.buffer = new CharArrayWriter();
+        this.columns = (header ? new HashMap() : null);
+        this.recordnumber = (header ? 0 : 1);
+        this.fieldnumber = 1;
+        this.openrecord = false;
+    }
+
+    @Override
+    public void execute() {
+
+        CSVReader csv = null;
+        try {
+            if (null == sourceString) { /*
+                                * Create a new Reader correctly decoding the
+                                * source stream
+                                */
+                csv = new CSVReader(this.url, this.encoding, this.buffersize);
+            }else{
+                csv = new CSVReader(sourceString, this.buffersize);
+            }
+            /* Start the document */
+            this.getSAXConsumer().setDocumentLocator(csv);
+            this.getSAXConsumer().startDocument();
+            this.getSAXConsumer().startPrefixMapping(NAMESPACE_PREFIX,
+                    NAMESPACE_URI);
+            this.indent(0);
+            this.startElement("document");
+
+            /* Allocate buffer and status for parsing */
+            boolean unescaped = true;
+            int prev = -1;
+            int curr = -1;
+
+            /* Parse the file reading characters one-by-one */
+            while ((curr = csv.read()) >= 0
+                    && (this.maxrecords == UNLIMITED_MAXRECORDS || recordnumber <= this.maxrecords)) {
+
+                /* Process any occurrence of the escape character */
+                if (curr == this.escape) {
+                    if ((unescaped) && (prev == this.escape)) {
+                        this.buffer.write(this.escape);
+                    }
+                    unescaped = !unescaped;
+                    prev = curr;
+                    continue;
+                }
+
+                /* Process any occurrence of the field separator */
+                if ((unescaped) && (curr == this.separator)) {
+                    this.dumpField();
+                    prev = curr;
+                    continue;
+                }
+
+                /* Process newline characters */
+                if ((unescaped) && ((curr == '\r') || (curr == '\n'))) {
+                    this.dumpField();
+                    this.dumpRecord();
+
+                    /* Record numbering */
+                    if (((curr == '\n') && (prev != '\r')) || (curr == '\r')) {
+                        this.recordnumber++;
+                    }
+
+                    /* Nothing else to do */
+                    prev = curr;
+                    continue;
+                }
+
+                /* Any other character simply gets added to the buffer */
+                this.buffer.write(curr);
+                prev = curr;
+            }
+
+            /* Terminate any hanging open record element (just in case) */
+            this.dumpField();
+            this.dumpRecord();
+
+            /* Terminate the document */
+            this.indent(0);
+            this.endElement("document");
+            this.getSAXConsumer().endPrefixMapping(NAMESPACE_PREFIX);
+            this.getSAXConsumer().endDocument();
+
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (SAXException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } finally {
+            if (null != csv) {
+                try {
+                    csv.close();
+                } catch (IOException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private void dumpField() throws SAXException {
+        if (this.buffer.size() < 1) {
+            this.fieldnumber++;
+            return;
+        }
+
+        if (!this.openrecord) {
+            this.indent(4);
+
+            if (this.recordnumber > 0) {
+                AttributesImpl attributes = new AttributesImpl();
+                String value = Integer.toString(this.recordnumber);
+                attributes.addAttribute("", "number", "number", "CDATA", value);
+                this.startElement("record", attributes);
+            } else {
+                this.startElement("header");
+            }
+            this.openrecord = true;
+        }
+
+        /* Enclode the field in the proper element */
+        String element = "field";
+        char array[] = this.buffer.toCharArray();
+        this.indent(8);
+
+        AttributesImpl attributes = new AttributesImpl();
+        String value = Integer.toString(this.fieldnumber);
+        attributes.addAttribute("", "number", "number", "CDATA", value);
+
+        if (this.recordnumber < 1) {
+            this.columns.put(new Integer(this.fieldnumber), new String(array));
+            element = "column";
+        } else if (this.columns != null) {
+            String header = (String) this.columns.get(new Integer(
+                    this.fieldnumber));
+            if (header != null) {
+                attributes
+                        .addAttribute("", "column", "column", "CDATA", header);
+            }
+        }
+
+        this.startElement(element, attributes);
+        this.getSAXConsumer().characters(array, 0, array.length);
+        this.endElement(element);
+        this.buffer.reset();
+
+        this.fieldnumber++;
+    }
+
+    private void dumpRecord() throws SAXException {
+        if (this.openrecord) {
+            this.indent(4);
+            if (this.recordnumber > 0) {
+                this.endElement("record");
+            } else {
+                this.endElement("header");
+            }
+            this.openrecord = false;
+        }
+        this.fieldnumber = 1;
+    }
+
+    private void indent(int level) throws SAXException {
+        this.getSAXConsumer().characters(INDENT_STRING, 0, level + 1);
+    }
+
+    private void startElement(String name) throws SAXException {
+        this.startElement(name, new AttributesImpl());
+    }
+
+    private void startElement(String name, Attributes atts) throws SAXException {
+        if (name == null)
+            throw new NullPointerException("Null name");
+        if (atts == null)
+            atts = new AttributesImpl();
+        String qual = NAMESPACE_PREFIX + ':' + name;
+        this.getSAXConsumer().startElement(NAMESPACE_URI, name, qual, atts);
+    }
+
+    private void endElement(String name) throws SAXException {
+        String qual = NAMESPACE_PREFIX + ':' + name;
+        this.getSAXConsumer().endElement(NAMESPACE_URI, name, qual);
+    }
+
+    private static final class CSVReader extends Reader implements Locator {
+
+        private String uri = null;
+        private Reader input = null;
+        private int column = 1;
+        private int line = 1;
+        private int last = -1;
+
+        private CSVReader(String csv, int buffer)
+                throws IOException {
+            Reader reader = new StringReader(csv);
+            this.input = new BufferedReader(reader, buffer);
+        }
+
+        private CSVReader(URL url, String encoding, int buffer)
+                throws IOException {
+            InputStream stream = url.openStream();
+            Reader reader = new InputStreamReader(stream, encoding);
+            this.input = new BufferedReader(reader, buffer);
+            this.uri = url.toExternalForm();
+        }
+
+        public String getPublicId() {
+            return null;
+        }
+
+        public String getSystemId() {
+            return this.uri;
+        }
+
+        public int getLineNumber() {
+            return this.line;
+        }
+
+        public int getColumnNumber() {
+            return this.column;
+        }
+
+        public void close() throws IOException {
+            this.input.close();
+        }
+
+        public int read() throws IOException {
+            int c = this.input.read();
+            if (c < 0)
+                return c;
+
+            if (((c == '\n') && (this.last != '\r')) || (c == '\r')) {
+                this.column = 1;
+                this.line++;
+            }
+
+            this.last = c;
+            return c;
+        }
+
+        public int read(char b[], int o, int l) throws IOException {
+            if (b == null)
+                throw new NullPointerException();
+            if ((o < 0) || (o > b.length) || (l < 0) || ((o + l) > b.length)
+                    || ((o + l) < 0)) {
+                throw new IndexOutOfBoundsException();
+            }
+            if (l == 0)
+                return 0;
+
+            int c = read();
+            if (c == -1)
+                return -1;
+            b[o] = (char) c;
+
+            int i = 1;
+            try {
+                for (i = 1; i < l; i++) {
+                    c = read();
+                    if (c == -1)
+                        break;
+                    b[o + i] = (char) c;
+                }
+            } catch (IOException ee) {
+                return i;
+            }
+            return i;
+        }
+    }
+    /*
+     * @Override public CacheKey constructCacheKey() { if (this.url == null) {
+     * throw new SetupException(this.getClass().getSimpleName() +
+     * " has no source."); } }
+     */
+}

Modified: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/pipeline/components/parameters/Parameters.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/pipeline/components/parameters/Parameters.java?rev=1243911&r1=1243910&r2=1243911&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/pipeline/components/parameters/Parameters.java (original)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/pipeline/components/parameters/Parameters.java Tue Feb 14 13:15:59 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.cocoon.pipeline.components.parameters;
 
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
@@ -24,7 +25,7 @@ public class Parameters {
     private Map<String, ? extends Object> values;
 
     public Parameters(Map<String, ? extends Object> configuration) {
-        values = configuration;
+        values = new HashMap<String, Object>(configuration);
     }
 
     public int getAsInteger(String key, int defaultValue) {
@@ -32,8 +33,12 @@ public class Parameters {
         if (value == null) {
             return defaultValue;
         }
-
-        return Integer.valueOf((String) value);
+        if (value instanceof Integer){
+            return (Integer) value;
+        }else if (value instanceof String){
+            return Integer.valueOf((String) value);
+        }
+        return defaultValue;
     }
 
     public String get(String key, String defaultValue) {
@@ -79,17 +84,20 @@ public class Parameters {
 
     public boolean getParameterAsBoolean(final String name,
             final boolean defaultValue) {
-        final String value = (String) getParameter(name, null);
+        final Object value = getParameter(name, null);
         if (value == null) {
             return defaultValue;
         }
-        if (value.equalsIgnoreCase("true")) {
-            return true;
-        } else if (value.equalsIgnoreCase("false")) {
-            return false;
-        } else {
-            return defaultValue;
+        if (value instanceof Boolean){
+            return (Boolean) value;
+        }else if (value instanceof String){
+            if (((String) value).equalsIgnoreCase("true")) {
+                return true;
+            } else if (((String) value).equalsIgnoreCase("false")) {
+                return false;
+            }
         }
+        return defaultValue;
     }
 
     public Parameters merge(final Parameters other) {

Modified: cocoon/cocoon3/trunk/cocoon-optional/src/main/resources/META-INF/cocoon/spring-optional/cocoon-optional-generators.xml
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/main/resources/META-INF/cocoon/spring-optional/cocoon-optional-generators.xml?rev=1243911&r1=1243910&r2=1243911&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/main/resources/META-INF/cocoon/spring-optional/cocoon-optional-generators.xml (original)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/main/resources/META-INF/cocoon/spring-optional/cocoon-optional-generators.xml Tue Feb 14 13:15:59 2012
@@ -23,5 +23,6 @@
 
   <bean name="generator:dir" class="org.apache.cocoon.optional.pipeline.components.sax.directory.DirectoryGenerator" scope="prototype" />
   <bean name="generator:html" class="org.apache.cocoon.optional.pipeline.components.sax.neko.NekoGenerator" scope="prototype" />
+  <bean name="generator:csv" class="org.apache.cocoon.optional.pipeline.components.sax.csv.CSVGenerator" scope="prototype" />
 
 </beans>

Added: cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/csv/CSVGeneratorTest.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/csv/CSVGeneratorTest.java?rev=1243911&view=auto
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/csv/CSVGeneratorTest.java (added)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/csv/CSVGeneratorTest.java Tue Feb 14 13:15:59 2012
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.optional.pipeline.components.sax.csv;
+
+import static org.custommonkey.xmlunit.XMLAssert.assertNodeTestPasses;
+
+import java.io.ByteArrayOutputStream;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cocoon.pipeline.NonCachingPipeline;
+import org.apache.cocoon.pipeline.Pipeline;
+import org.apache.cocoon.sax.SAXPipelineComponent;
+import org.apache.cocoon.sax.component.XMLSerializer;
+import org.custommonkey.xmlunit.examples.CountingNodeTester;
+import org.junit.Test;
+import org.w3c.dom.Node;
+
+public final class CSVGeneratorTest {
+    @Test
+    public void testPipelineWithDirectoryGenerator() throws Exception {
+        ByteArrayOutputStream baos = getPipelineResult();
+        System.out.println(new String(baos.toByteArray()));
+        CountingNodeTester countingNodeTester = new CountingNodeTester(79);
+        assertNodeTestPasses(new String(baos.toByteArray()),
+                countingNodeTester, Node.ELEMENT_NODE);
+    }
+
+    private ByteArrayOutputStream getPipelineResult()
+            throws URISyntaxException, MalformedURLException, Exception {
+        Pipeline<SAXPipelineComponent> pipeline = new NonCachingPipeline<SAXPipelineComponent>();
+
+        CSVGenerator generator = new CSVGenerator(csv);
+        Map<String, Object> parameters = new HashMap<String, Object>();
+        parameters.put("process-headers", true);
+        parameters.put("max-records", 10);
+        generator.setConfiguration(parameters);
+        pipeline.addComponent(generator);
+        pipeline.addComponent(new XMLSerializer());
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        pipeline.setup(baos);
+        pipeline.execute();
+        return baos;
+    }
+
+    /*
+     * Using here a string since the csv file needs license headers for RAT, but the generator
+     * does not like this header and tries to parse it.
+     * 
+     * Here a listening of a couple of South Park episodes
+     */
+    private final String csv = "number,season,episode,production code,airdate,title,special\n"
+            + "1,1,1,\"101\",13/Aug/97,\"Cartman Gets an Anal Probe\"\n"
+            + "2,1,2,\"103\",20/Aug/97,\"Volcano\"\n"
+            + "3,1,3,\"102\",27/Aug/97,\"Weight Gain 4000\"\n"
+            + "4,1,4,\"104\",03/Sep/97,\"Big Gay Al's Big Gay Boat Ride\"\n"
+            + "5,1,5,\"105\",10/Sep/97,\"An Elephant Makes Love to a Pig\"\n"
+            + "6,1,6,\"106\",17/Sep/97,\"Death\"\n"
+            + "7,1,7,\"107\",29/Oct/97,\"Pinkeye\"\n"
+            + "8,1,8,\"109\",19/Nov/97,\"Starvin' Marvin\"\n"
+            + "9,1,9,\"110\",17/Dec/97,\"Mr. Hankey, the Christmas Poo\"\n"
+            + "10,1,10,\"108\",04/Feb/98,\"Damien\"\n"
+            + "11,1,11,\"111\",11/Feb/98,\"Tom's Rhinoplasty\"\n"
+            + "12,1,12,\"112\",18/Feb/98,\"Mecha-Streisand\"\n"
+            + "13,1,13,\"113\",25/Feb/98,\"Cartman's Mom is a Dirty Slut (1)\"\n"
+            + "14,2,1,\"201\",01/Apr/98,\"Terrance & Phillip in \"\"Not Without My Anus\"\"\"\n"
+            + "15,2,2,\"202\",22/Apr/98,\"Cartman's Mom is Still a Dirty Slut (2)\"\n"
+            + "16,2,3,\"204\",20/May/98,\"Ike's Wee Wee\"\n"
+            + "17,2,4,\"203\",27/May/98,\"Chickenlover\"\n"
+            + "18,2,5,\"205\",03/Jun/98,\"Conjoined Fetus Lady\"\n"
+            + "19,2,6,\"206\",10/Jun/98,\"The Mexican Staring Frog of Southern Sri Lanka\"\n"
+            + "20,2,7,\"207\",17/Jun/98,\"City on the Edge of Forever (a.k.a. Flashbacks)\"\n"
+            + "21,2,8,\"208\",24/Jun/98,\"Summer Sucks\",n\n";
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.