/*
 * Copyright (C) 2015 Siara Logics (cc)
 *
 * Licensed 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.
 * 
 * @author Arundale R.
 *
 */
package cc.siara.csv_ml;

import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import cc.siara.csv.CSVParser;

/**
 * Constructs csv_ml string from Document object
 * 
 * @author Arundale R.
 * @since 1.0
 */
public class Outputter {

    /**
     * Constructs csv_ml string from Document object
     * 
     * @param dom
     *            Input document
     * @return output csv_ml string
     */
    public static String generate(Document dom) {

        // Initialize schema with default directive. TODO: to handle encoding,
        // root and namespaces
        StringBuffer schema = new StringBuffer("csv_ml,1.0\n");

        StringBuffer data = new StringBuffer();
        outputCSVRecursively(dom.getDocumentElement(), schema, data, "");
        return schema.append("end_schema\n").append(data).toString();

    }

    /**
     * Builds the csv_ml string starting at the root node
     * 
     * @param ele Initially the root element
     * @param schema
     * @param data
     * @param hierarchy_space_prefix
     */
    private static void outputCSVRecursively(Element ele, StringBuffer schema,
            StringBuffer data, String hierarchy_space_prefix) {

        String node_name = ele.getNodeName();

        boolean is_schema_updated = false;
        if (schema.indexOf("\n" + hierarchy_space_prefix + node_name + ",") != -1)
            is_schema_updated = true;

        // Export node
        // TODO: does not generate data for root node
        if (ele.getParentNode().getParentNode() != null) {

            // Export node
            if (!is_schema_updated)
                schema.append(hierarchy_space_prefix).append(node_name);
            data.append(hierarchy_space_prefix).append(node_name);

            // Export attributes
            NamedNodeMap attributes = ele.getAttributes();
            for (int j = 0; j < attributes.getLength(); j++) {
                if (!is_schema_updated)
                    schema.append(",").append(attributes.item(j).getNodeName());
                data.append(",").append(
                        CSVParser.encodeToCSVText(attributes.item(j)
                                .getNodeValue()));
            }

            // TODO: Is text content to be exported?
            // String tc = ele.getTextContent();
            // if (tc != null && !tc.equals(""))
            // data.append(",").append(CSVParser.encodeToCSVText(tc));

            // Export CData sections
            NodeList childNodes = ele.getChildNodes();
            for (int i = 0; i < childNodes.getLength(); i++) {
                if (childNodes.item(i).getNodeType() != Node.CDATA_SECTION_NODE)
                    continue;
                CDATASection cdata_section = (CDATASection) childNodes.item(i);
                data.append(",").append(
                        CSVParser.encodeToCSVText(cdata_section.getData()));
            }
            if (!is_schema_updated)
                schema.append("\n");
            data.append("\n");
            hierarchy_space_prefix += " ";

        }

        // Recurse children
        NodeList childNodes = ele.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            if (childNodes.item(i).getNodeType() != Node.ELEMENT_NODE)
                continue;
            outputCSVRecursively((Element) childNodes.item(i), schema, data,
                    hierarchy_space_prefix);
        }

    }

}

@@ -1575,24 +1575,656 @@
 ();%0A%0A    %7D%0A%0A
+    /**%0A     * Checks whether encoding is necessary and encodes by enclosing in double%0A     * quotes, in which case, any double quotes appearing in data need to be%0A     * escaped.%0A     * %0A     * @param value%0A     * @return%0A     */%0A    public static String encodeToCSVText(String value) %7B%0A        if (value == null)%0A            return value;%0A        if (value.indexOf(',') != -1 %7C%7C value.indexOf('%5Cn') != -1%0A                %7C%7C value.indexOf(%22/*%22) != -1) %7B%0A            if (value.indexOf('%22') != -1)%0A                value = value.replace(%22%5C%22%22, %22%5C%22%5C%22%22);%0A            value = (%22%5C%22%22 + value + %22%5C%22%22);%0A        %7D%0A        return value;%0A    %7D%0A%0A
     /**%0A    
@@ -2302,16 +2302,34 @@
 aram ele
+%0A     *           
  Initial
@@ -3467,34 +3467,24 @@
             
-CSVParser.
 encodeToCSVT
@@ -3509,41 +3509,8 @@
 m(j)
-%0A                                
 .get
@@ -3729,26 +3729,16 @@
 .append(
-CSVParser.
 encodeTo
@@ -4167,18 +4167,8 @@
     
-CSVParser.
 enco

Add javadoc