Package net.sf.xbus.protocol.csv

Source Code of net.sf.xbus.protocol.csv.CSVSerializer

package net.sf.xbus.protocol.csv;

import java.util.Hashtable;

import net.sf.xbus.base.core.Constants;
import net.sf.xbus.base.core.XException;
import net.sf.xbus.base.core.config.Configuration;
import net.sf.xbus.base.xml.XDomSupport;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* <code>CSVSerializer</code> serves for serializing records stored in a DOM
* tree according to a CSV type message
* <p>
* The DOM tree structure is described in the
* {@link net.sf.xbus.protocol.csv.CSVParser CSVParser} documentation.
* </p>
* <ul>
* <li>The serialization result is a String.</li>
* <li>Every record is serialized into one line</li>
* <li>The fields are separated by the FieldSeparator which is set in the
* configuration. (default value in xbus.conf, overwritting possible for every
* process</li>
* <li>The QuoteChar is surrounding fields which contain the QuoteChar
* character, a line break, a FieldSeparator or spaces. Which character is used
* is indicated in xbus.conf of in the process configuration. </li>
* <li>The HasHeader configuration key indicates if an header should be written
* into the CSV file</li>
* <li>If AlwaysQuote is set true in the configuration, all fields are
* surrounded by the QuoteChar</li>
* </ul>
*
* @author Stephan D�wel, Wolfgang K�ppl
*/
public class CSVSerializer
{

  private static Hashtable instances = new Hashtable();
  private static final Object classLock = CSVSerializer.class;

  private String fieldSeparator;
  private String quoteChar;
  private String quotePair;
  private boolean alwaysQuote;
  private boolean hasHeader;
  private String lineSeparator;

  /**
   * @param system the name of the process
   * @throws XException
   */
  public CSVSerializer(String system) throws XException
  {
    readConfig(system);
  }

  /**
   * @param sourceType the name of the process
   * @return an instance of the CSVSerializer class
   */
  protected static CSVSerializer getInstance(String sourceType)
      throws XException
  {
    synchronized (classLock)
    {
      if (sourceType == null || sourceType.length() == 0)
        throw new XException(Constants.LOCATION_INTERN,
            Constants.LAYER_PROTOCOL,
            Constants.PACKAGE_PROTOCOL_CSV, "1");

      CSVSerializer instance = (CSVSerializer) instances.get(Thread
          .currentThread().getName()
          + sourceType);
      if (instance == null)
      { // no suitable instance available yet
        instance = new CSVSerializer(sourceType);
        instances.put(Thread.currentThread().getName() + sourceType,
            instance);
      } // if (instance==null)
      return instance;
    }
  }

  /**
   * @return Returns the lineSeparator.
   */
  public String getLineSeparator()
  {
    return lineSeparator;
  }

  /**
   * Serializes a DOM tree into a CSV message.
   *
   * @param doc The information that is parsed into CSV format. Has to be a
   *            DOM tree.
   * @return The String of the serialized document.
   */
  protected String serialize(Document doc) throws XException
  {
    String result = "";
    // delete all the gaps(spaces) between the tags
    try
    {
      XDomSupport.deleteWhitespaceTextInElementNodesAndComments(doc);
    }
    catch (Exception e)
    {
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL, Constants.PACKAGE_PROTOCOL_CSV,
          "3");
    }

    // do we want to write out a header?
    if (hasHeader)
    {
      result = returnSerializedHeader(doc);
    }// if(hasHeder)

    Node recordsNode = doc.getElementsByTagName("Records").item(0);
    NodeList recordsList = recordsNode.getChildNodes();

    // go through all records and process every single of them
    for (int i = 0; i < recordsList.getLength(); i++)
    {
      result += serializeOneLine(recordsList.item(i).getChildNodes());
    }
    return result;
  }

  /**
   * Returns the serialized header line. The headers for the fields are the
   * tag names inside the <Header>-Tags
   *
   * @param doc The document containing the header information.
   * @return The header String
   * @throws XException
   */
  private String returnSerializedHeader(Document doc) throws XException
  {
    String header = null;
    Node headerNode = doc.getElementsByTagName("Header").item(0);
    if (headerNode != null)
    {
      NodeList headerElements = headerNode.getChildNodes();
      header = serializeOneLine(headerElements);
    }
    else
    {
      Node firstRecord = doc.getElementsByTagName("Records").item(0)
          .getFirstChild();
      NodeList fields = firstRecord.getChildNodes();
      StringBuffer line = new StringBuffer();
      for (int i = 0; i < fields.getLength(); i++)
      {
        String fieldName = fields.item(i).getNodeName();
        // doubleQuote all quoteChars
        if (fieldName.indexOf(quoteChar) >= 0)
          fieldName = fieldName.replaceAll(quoteChar, quotePair);

        // do we always quote or have quote, fieldSeparator, lineBreak
        // or
        // space in the field
        if (alwaysQuote || fieldName.indexOf(quoteChar) >= 0
            || fieldName.indexOf(lineSeparator) >= 0
            || fieldName.indexOf(fieldSeparator) >= 0)
        {
          line.append(quoteChar);
          line.append(fieldName);
          line.append(quoteChar);
        } // then (alwaysQuote || fieldName.indexOf(quoteChar) >= 0 ||
          // fieldName.indexOf(lineSeparator) >= 0 ||
          // fieldName.indexOf(fieldSeparator) >= 0)
        else
          line.append(fieldName);

        // last field?
        if (i < fields.getLength() - 1)
          line.append(fieldSeparator);
        else
          line.append(lineSeparator);
      } // for (int i=0; i<fields.getLength(); i++)
      if (line.length() > 0)
        header = line.toString();
    } // else (headerNode != null)
    if (header == null)
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL, Constants.PACKAGE_PROTOCOL_CSV,
          "2");
    return header;
  } // returnSerializedHeader(Document doc)

  /**
   * Parses one set of fields (one record or one header) into a CSV entry
   *
   * @param lineElements The elements of the entry. Every node in the list is
   *            one field in the entry.
   * @return The String of the serialized entry in CSV format.
   */
  private String serializeOneLine(NodeList lineElements)
  {
    StringBuffer text = new StringBuffer();
    for (int i = 0; i < lineElements.getLength(); i++)
    {
      Node currentNode = lineElements.item(i);
      StringBuffer currentText = new StringBuffer();
      NodeList textNodes = currentNode.getChildNodes();
      for (int j = 0; j < textNodes.getLength(); j++)
      {
        currentText.append(textNodes.item(j).getNodeValue());
      }

      String fieldValue = currentText.toString();
      // doubleQuote all quoteChars
      if (fieldValue.indexOf(quoteChar) >= 0)
      {
        fieldValue = fieldValue.replaceAll(quoteChar, quotePair);
      }

      // do we always quote or have quote, fieldSeparator, lineBreak or
      // space in the field
      if (alwaysQuote || fieldValue.indexOf(quoteChar) >= 0
          || fieldValue.indexOf(lineSeparator) >= 0
          || fieldValue.indexOf(fieldSeparator) >= 0
      /* || currentText.indexOf(" ") >= 0 */)
      {
        text.append(quoteChar);
        text.append(fieldValue);
        text.append(quoteChar);
      }
      else
      {
        text.append(currentText);
      }
      // last field?
      if (i < lineElements.getLength() - 1)
      {
        text.append(fieldSeparator);
      }
      else
      {
        text.append(lineSeparator);
      }
    }
    return text.toString();
  }

  /**
   * Reads out the configuration entries for the Serialization. Defaults
   * values are set as MessageDefaults_CSVMessage_Key in xbus.conf. These can
   * be overwritten for every process.
   *
   * @param sectionName The name of the process.
   * @throws XException
   */
  private void readConfig(String sectionName) throws XException
  {
    Configuration config = Configuration.getInstance();
    Configuration xBusConfig = Configuration.getInstance("xbus");
    String tempVariable = null;

    // get Field Separator
    if ((fieldSeparator = config.getValueOptional(Constants.CHAPTER_SYSTEM,
        sectionName, Constants.KEY_CSV_FIELD_SEPARATOR)) == null)
    {
      fieldSeparator = xBusConfig.getValue("MessageDefaults",
          "CSVMessage", Constants.KEY_CSV_FIELD_SEPARATOR);
    }

    // get Quote Character
    if ((quoteChar = config.getValueOptional(Constants.CHAPTER_SYSTEM,
        sectionName, Constants.KEY_CSV_QUOTE_CHAR)) == null)
    {
      quoteChar = xBusConfig.getValue("MessageDefaults", "CSVMessage",
          Constants.KEY_CSV_QUOTE_CHAR);
    }

    if (quoteChar == null || fieldSeparator == null
        || quoteChar.equals(fieldSeparator))
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL, Constants.PACKAGE_PROTOCOL_CSV,
          "15");

    quotePair = quoteChar + quoteChar;

    // get configuration entry if containing header
    if ((tempVariable = config.getValueOptional(Constants.CHAPTER_SYSTEM,
        sectionName, Constants.KEY_CSV_HAS_HEADER)) == null)
    {
      hasHeader = xBusConfig.getValueAsBoolean("MessageDefaults",
          "CSVMessage", Constants.KEY_CSV_HAS_HEADER);
    }
    else if (tempVariable.equalsIgnoreCase(Constants.CONFIGURATION_TRUE))
    {
      hasHeader = true;
    }
    else
    {
      hasHeader = false;
    }

    // get configuration if all fields should be quoted
    if ((tempVariable = config.getValueOptional(Constants.CHAPTER_SYSTEM,
        sectionName, Constants.KEY_CSV_ALWAYS_QUOTE)) == null)
    {
      alwaysQuote = xBusConfig.getValueAsBoolean("MessageDefaults",
          "CSVMessage", Constants.KEY_CSV_ALWAYS_QUOTE);
    }
    else if (tempVariable.equalsIgnoreCase(Constants.CONFIGURATION_TRUE))
    {
      alwaysQuote = true;
    }
    else
    {
      alwaysQuote = false;
    }

    // set line separator
    lineSeparator = Constants.LINE_SEPERATOR;
    String platform = config.getValueOptional(Constants.CHAPTER_SYSTEM,
        sectionName, "Platform");
    if (platform != null)
    {
      lineSeparator = Constants.getLineSeperator(platform);
    }
  }

}
TOP

Related Classes of net.sf.xbus.protocol.csv.CSVSerializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.