Package net.sf.xbus.protocol.records

Source Code of net.sf.xbus.protocol.records.RecordTypeSerializer

package net.sf.xbus.protocol.records;

import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

import net.sf.xbus.base.bytearraylist.ByteArrayConverter;
import net.sf.xbus.base.bytearraylist.ByteArrayConverterFactory;
import net.sf.xbus.base.bytearraylist.ByteArrayList;
import net.sf.xbus.base.core.Constants;
import net.sf.xbus.base.core.XException;
import net.sf.xbus.base.xml.XDomSupport;

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

/**
* <code>RecordTypeSerializer</code> serves for serializing records stored in
* a DOM tree according to a record type structure.
* <p>
* The DOM tree structure is described in the
* {@link net.sf.xbus.protocol.records.RecordTypeParser RecordTypeParser}
* documentation.
* </p>
* <p>
* The serialization result is a String. <br>
* The string structure is described by a xml file - in particular the contained
* record types. Such describing files are of document type
* <code>InterfaceSpec</code> declared in "InterfaceSpec.dtd". The structure
* of the internal DOM tree to serialise is described on the
* {@link net.sf.xbus.protocol.records.RecordTypeParser RecordTypeParser}
* documentation page.
* </p>
*
* @author Lars Me�ner, Stehan D�wel
*/
public class RecordTypeSerializer extends RecordTypeManipulator
{

  // //////////////////////
  // Static fields
  // //////////////////////

  /**
   * <code>instances</code> stores the instances by thread and the interface
   * type.
   */
  private static Hashtable instances = new Hashtable();
  private static final Object classLock = RecordTypeSerializer.class;

  // //////////////////////
  // Constructors
  // //////////////////////

  /**
   * Just the standard constructor.
   */
  private RecordTypeSerializer() throws XException
  {
    super();
  } // RecordTypeParser()

  // //////////////////////
  // Static methods
  // //////////////////////

  /**
   * <code>getInstance()</code> retrieves the an instance of
   * <code>RecordTypeSerializer</code>.
   *
   * @param sourceType the name for the parsed structure as it is derived from
   *            the DOM tree with the interface content
   * @throws XException in case of missing <code>sourceType</code>
   */
  public static RecordTypeSerializer getInstance(String sourceType,
      int interfaceContentClass) throws XException
  {
    synchronized (classLock)
    {
      if (sourceType == null || sourceType.length() == 0)
        throw new XException(Constants.LOCATION_INTERN,
            Constants.LAYER_PROTOCOL,
            Constants.PACKAGE_PROTOCOL_RECORDS, "68");

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

  /**
   * Method getByteArrayConverter.
   *
   * @return ByteArrayConverter
   */
  protected ByteArrayConverter getByteArrayConverter() throws XException
  {
    return ByteArrayConverterFactory.getConverter(sourceType);
  }

  // /////////////////////////////////////////
  // Serializing the contents
  // /////////////////////////////////////////

  /**
   * <code>serialize</code> serializes the specified DOM tree due to the
   * record type definition.
   *
   * @param docContent the DOM tree with the interface content
   * @return the serialized string
   * @throws XException in case of an unexpected value
   */
  public Object serialize(Document docContent) throws XException
  {
    if (interfaceStructure == null)
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL,
          Constants.PACKAGE_PROTOCOL_RECORDS, "99");

    // The root element has the content type as xml tag.
    Element root = docContent.getDocumentElement();
    if (contentType == null || !contentType.equals(root.getNodeName()))
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL,
          Constants.PACKAGE_PROTOCOL_RECORDS, "120");

    Node node = root.getFirstChild();
    Object result = null;
    if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
    {
      result = "";
    }
    else if (interfaceContentClass == Constants.IFCONTENTCLASS_BYTEARRAYLIST)
    {
      result = new ByteArrayList();
    }
    else
    {
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL,
          Constants.PACKAGE_PROTOCOL_RECORDS, "100");
    }

    if (node == null)
    {
      return result;
    }

    if (!node.getNodeName().equals("Records"))
    { // not the records section - thus a header
      if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
        result = serializeHeader(node) + Constants.LINE_SEPERATOR;
      else
        ((ByteArrayList) result).add((byte[]) serializeHeader(node));
      // Go to the records section
      node = node.getNextSibling();
    } // if (!node.getNodeName().equals("Records"))

    // Now the records section
    if (node == null || !node.getNodeName().equals("Records"))
    {
      List params = new Vector();
      params.add("Records expected");
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL,
          Constants.PACKAGE_PROTOCOL_RECORDS, "122", params);
    } // if (node == null || !node.getNodeName().equals("Records"))
    if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
      result = result + (String) serializeRecords(node);
    else
      ((ByteArrayList) result)
          .addAll((ByteArrayList) serializeRecords(node));

    // Go to trailer or end
    node = node.getNextSibling();
    if (node != null)
    { // trailer found
      if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
        result = result + (String) serializeTrailer(node);
      else
        ((ByteArrayList) result).add((byte[]) serializeTrailer(node));
      // Go to end
      node = node.getNextSibling();
    } // if (node!=null)
    else if (result != null
        && interfaceContentClass == Constants.IFCONTENTCLASS_STRING
        && ((String) result).length() > 0)
      // no trailer
      // Cut off the line separator after the last record.
      result = ((String) result).substring(0, ((String) result).length()
          - Constants.LINE_SEPERATOR.length());

    // Must be the end.
    if (node != null)
    {
      List params = new Vector();
      params.add(node.getNodeName());
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL,
          Constants.PACKAGE_PROTOCOL_RECORDS, "123", params);
    } // if (node != null)

    return result;
  } // serialize(Document docContent)

  /**
   * <code>serializeHeader</code> parses the header.
   *
   * @param headerNode the header in the content DOM tree
   * @return the serialized header as {@link java.lang.String string}
   * @throws XException in case of an unexpected value
   */
  private Object serializeHeader(Node headerNode) throws XException
  { // Easy: no record type identification necessary
    // Jump directly to contained fields.
    return serializeFieldsAndGroups(headerNode, headerSpec);
  } // serializeHeader(Node headerNode)

  /**
   * <code>serializeRecords</code> serializes the records section.
   *
   * @param recordsNode
   * @return String
   */
  private Object serializeRecords(Node recordsNode) throws XException
  {
    String tag = recordsNode.getNodeName();
    if (tag == null || !tag.equals("Records"))
    {
      List params = new Vector();
      params.add("Records expected");
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL,
          Constants.PACKAGE_PROTOCOL_RECORDS, "122", params);
    } // if (tag == null || !tag.equals("Records"))
    Object result = null;
    if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
      result = "";
    else
      result = new ByteArrayList();
    Node recordGroup = recordsNode.getFirstChild();
    while (recordGroup != null)
    { // Loop over the record groups or just a dummy loop
      // Two possibilities: directly first record or first record group
      Node record = recordGroup;
      if (recordGroup.getNodeName().equals("RecordGroup"))
        // In case of a record group go one level deeper to the first
        // record of the group
        record = recordGroup.getFirstChild();
      while (record != null)
      { // loop over the records in the group - or all if no record
        // groups are present
        // The record type is identified by the xml tag.
        // Get it and jum to the contained fields.
        if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
          result = result
              + (String) serializeFieldsAndGroups(record,
                  getRecordTypeSpec(record.getNodeName()))
              + Constants.LINE_SEPERATOR;
        else
          ((ByteArrayList) result)
              .add((byte[]) serializeFieldsAndGroups(record,
                  getRecordTypeSpec(record.getNodeName())));
        // Go to next record
        record = record.getNextSibling();
      } // while (record!=null)
      if (recordGroup.getNodeName().equals("RecordGroup"))
      { // Go to next record group
        recordGroup = recordGroup.getNextSibling();
      } // if (recordGroup.getNodeName().equals("RecordGroup"))
      else
        // no record groups, simply end the loop
        recordGroup = null;
    } // while (recordGroup!=null)
    return result;
  } // serializeRecords(Node recordsNode)

  /**
   * <code>serializeTrailer</code> parses the header.
   *
   * @param trailerNode the trailer in the content DOM tree
   * @return the serialized trailer as {@link java.lang.String string}
   * @throws XException in case of an unexpected value
   */
  private Object serializeTrailer(Node trailerNode) throws XException
  { // Easy: no record type identification necessary
    // Jump directly to contained fields.
    return serializeFieldsAndGroups(trailerNode, trailerSpec);
  } // serializeTrailer(Node trailerNode)

  /**
   * <code>serializeFieldsAndGroups</code> serializes the fields and group
   * references within a record type - including header and trailer.
   *
   * @param recordNode the record node in the result DOM tree
   * @param recordType the record type specification node in the structure
   *            descrition to get the field specs from
   * @return the serialized records as {@link java.lang.String string}
   * @throws XException in case of an unexpected value
   */
  private Object serializeFieldsAndGroups(Node recordNode, Node recordType)
      throws XException
  { // To avoid permanent string manipulations, a StringBuffer is used.
    int length = RecordTypeDescriptionChecker.computeRecordLength(
        recordType, groupsSpec);
    // Length for the buffer.
    int pos = 0;
    // Position in the buffer to put the next field.
    Object buffer = null;
    if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
      buffer = new StringBuffer(length);
    else
      buffer = new byte[length];

    try
    // for casting to XException
    {
      NodeList fieldSpecs = recordType.getChildNodes();
      // The next available field node in the content DOM tree.
      // array for call by reference
      Node[] fieldNode = new Node[1];
      // the first field
      fieldNode[0] = recordNode.getFirstChild();

      for (int i = 0; i < fieldSpecs.getLength(); i++)
      { // Loop over all fields and group references in the sturcture
        // description
        Element fieldSpec = (Element) fieldSpecs.item(i);
        if (fieldSpec.getNodeName().equals("Field"))

          // a single field
          pos = serializeField(fieldSpec, buffer, pos, fieldNode);
        // May have moved the actual field node in the content DOM tree

        else if (fieldSpec.getNodeName().equals("Group"))

          // a field group
          pos = serializeGroup(fieldSpec, buffer, pos, fieldNode);
        // May have moved the actual field node in the content DOM tree

      } // for (int i=0; i<fieldSpecs.getLength(); i++)

      // All record fields in the content DOM tree should be serialized.
      if (fieldNode[0] != null)
      {
        List params = new Vector();
        params.add(fieldNode[0].getNodeName());
        throw new XException(Constants.LOCATION_INTERN,
            Constants.LAYER_PROTOCOL,
            Constants.PACKAGE_PROTOCOL_RECORDS, "125", params);
      }
    } // try
    catch (ClassCastException e)
    {
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL,
          Constants.PACKAGE_PROTOCOL_RECORDS, "0", e);
    } // catch
    if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
      return new String((StringBuffer) buffer);
    else
      return buffer;
  } // serializeFieldsAndGroups(Node recordNode, Node recordType)

  /**
   * <code>serializeGroup</code> serializes the fields of a field group
   * defined in the interface structure description.
   *
   * @param groupRef the group reference in the structure description
   * @param buffer the buffer to fill with the serialized field contents
   * @param pos the position in the buffer to start the filling
   * @param fieldNode the next available field node in the content DOM tree -
   *            array for call by reference
   * @return the buffer position to start the next filling at
   * @throws XException in case of an unexpected value
   */
  private int serializeGroup(Element groupRef, Object buffer, int pos,
      Node[] fieldNode) throws XException
  {
    try
    // for casting to XException
    {
      NodeList fieldSpecs = RecordTypeDescriptionChecker.getGroupSpec(
          groupRef.getAttribute("Name"), groupsSpec).getChildNodes();
      // fields in the group
      for (int i = 0; i < fieldSpecs.getLength(); i++)
        pos = serializeField((Element) fieldSpecs.item(i), buffer, pos,
            fieldNode);
    } // try
    catch (ClassCastException e)
    {
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL,
          Constants.PACKAGE_PROTOCOL_RECORDS, "0", e);
    } // catch
    return pos;
  } // serializeGroup(Element groupRef,StringBuffer buffer,int pos,Node[]
  // fieldNode)

  /**
   * <code>serializeField</code> serializes the fields of a field group
   * defined in the interface structure description.
   *
   * @param fieldSpec the field specification in the structure description
   * @param buffer the buffer to fill with the serialized field contents
   * @param pos the position in the buffer to start the filling
   * @param fieldNode the next available field node in the content DOM tree -
   *            array for call by reference
   * @return the buffer position to start the next filling at
   * @throws XException in case of an unexpected value
   */
  private int serializeField(Element fieldSpec, Object buffer, int pos,
      Node[] fieldNode) throws XException
  {
    try
    // for casting to XException
    {
      String fieldFormat = fieldSpec.getAttribute("Format");
      if (fieldFormat == null || fieldFormat.length() == 0)
      {
        List params = new Vector();
        params.add("Format");
        params.add(((Element) fieldSpec.getParentNode())
            .getAttribute("Name"));
        params.add(fieldSpec.toString());
        throw new XException(Constants.LOCATION_INTERN,
            Constants.LAYER_PROTOCOL,
            Constants.PACKAGE_PROTOCOL_RECORDS, "82", params);
      }

      // How many characters?
      int length = Integer.parseInt(fieldSpec.getAttribute("Length"));

      if (fieldFormat.equals("blank"))
      { // only filler - no corresponding node in the content DOM tree
        if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
          for (int i = 0; i < length; i++)
            ((StringBuffer) buffer).insert(pos + i, ' ');
        else
          fillByteArray((byte[]) buffer, pos, length, "");
      } // then (fieldFormat.equals("blank"))
      else
      { // Not just filler
        String fieldName = fieldSpec.getAttribute("Name");
        String nodeName = null;
        if (fieldNode[0] != null)
          nodeName = fieldNode[0].getNodeName();
        if (fieldName == null)
        {
          List params = new Vector();
          params.add("Name");
          params.add(((Element) fieldSpec.getParentNode())
              .getAttribute("Name"));
          params.add(fieldSpec.toString());
          throw new XException(Constants.LOCATION_INTERN,
              Constants.LAYER_PROTOCOL,
              Constants.PACKAGE_PROTOCOL_RECORDS, "82", params);
        } // if (fieldName == null)

        // The field value may be stored in the content DOM tree or
        // a standard value may be used.
        String value = "";
        // standard for alphanumeric fields
        if (fieldFormat.equals("num"))
          value = "0";
        // standard for numeric fields

        if (fieldName.equals(nodeName))
        { // The value is given in the content DOM tree.
          value = XDomSupport.getNodeText(fieldNode[0]);
          // Set the next available field in the content DOM tree one
          // further
          fieldNode[0] = fieldNode[0].getNextSibling();
        } // if (fieldName.equals(nodeName))

        // Now a value - read from the content DOM tree or standard - is
        // given.
        if (fieldFormat.equals("const"))
        {
          String constValue = fieldSpec.getAttribute("Value");
          // value specified in the interface description
          byte[] constValueBytes = null;
          if (interfaceContentClass == Constants.IFCONTENTCLASS_BYTEARRAYLIST)
          {
            constValueBytes = byteArrayConverter
                .stringToByteArray(constValue);
          } // if (interfaceContentClass ==
          // Constants.IFCONTENTCLASS_BYTEARRAYLIST)
          if (!constValue.equals(value))
          { // The interface description must specify a value of
            // correct
            // length.
            // If the content DOM tree has a value, they must be
            // identical (after triming).
            List params = new Vector();
            params.add(((Element) fieldSpec.getParentNode())
                .getAttribute("Name"));
            params.add(fieldSpec.getAttribute("Name"));
            params.add("?");
            throw new XException(Constants.LOCATION_INTERN,
                Constants.LAYER_PROTOCOL,
                Constants.PACKAGE_PROTOCOL_RECORDS, "106",
                params);
          } // if (constValue == null || constValueLength != length
            // ||
          // value.length() > 0 && !constTrimed.equals(value))

          if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
            ((StringBuffer) buffer).insert(pos, constValue);
          else
            for (int i = 0; i < length; i++)
              ((byte[]) buffer)[pos + i] = constValueBytes[i];
        } // then (fieldFormat.equals("const"))
        else if (fieldFormat.equals("alpha"))
        {
          int valueLength = value.length();
          byte[] valueBytes = null;
          if (interfaceContentClass == Constants.IFCONTENTCLASS_BYTEARRAYLIST)
          {
            valueBytes = byteArrayConverter
                .stringToByteArray(value);
            valueLength = valueBytes.length;
          }
          if (length < valueLength)
          {
            value = value.trim();
            valueLength = value.length();
            if (interfaceContentClass == Constants.IFCONTENTCLASS_BYTEARRAYLIST)
            {
              valueBytes = byteArrayConverter
                  .stringToByteArray(value);
              valueLength = valueBytes.length;
            }
            if (length < valueLength)
            {
              if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
              {
                List params = new Vector();
                params
                    .add(((Element) fieldSpec
                        .getParentNode())
                        .getAttribute("Name"));
                params.add(fieldSpec.getAttribute("Name"));
                params.add(value);
                throw new XException(Constants.LOCATION_INTERN,
                    Constants.LAYER_PROTOCOL,
                    Constants.PACKAGE_PROTOCOL_RECORDS,
                    "131", params);
              } // if (interfaceContentClass ==
              // Constants.IFCONTENTCLASS_STRING)
              else
              {
                valueBytes = byteArrayConverter
                    .stringToByteArray(value, length);
                valueLength = valueBytes.length;
              }
            }
          }
          if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
          {
            ((StringBuffer) buffer).insert(pos, value);
            // Fill in blanks if the value is to short.
            for (int i = 0; i < length - value.length(); i++)
              ((StringBuffer) buffer).insert(pos + value.length()
                  + i, ' ');
          }
          else
            fillByteArray((byte[]) buffer, pos, length, value);
        } // then (fieldFormat.equals("alpha"))
        else if (fieldFormat.equals("num"))
        { // First look for a leading sign
          int start = 0;
          if (value.length() > 0)
          {
            char sign = value.charAt(0);
            if (sign == '+' || sign == '-')
            {
              if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
              {
                ((StringBuffer) buffer).insert(pos, sign);
                start = 1;
              }
              else
              {
                byte[] signBytes = byteArrayConverter
                    .stringToByteArray("" + sign);
                start = signBytes.length;
                for (int i = 0; i < start; i++)
                  ((byte[]) buffer)[pos + i] = signBytes[i];
              }
              value = value.substring(1).trim();
            } // if (sign=='+' || sign=='-')
          } // if (value.length()>0)

          // Look for a decimal point
          String decimalPoint = fieldSpec
              .getAttribute("DecimalPoint");
          int decPointPos = -1;
          if (decimalPoint != null && decimalPoint.length() > 0)
          {
            char decimalP = '.';
            if (decimalPoint.equals("comma"))
              decimalP = ',';
            else if (!decimalPoint.equals("dot"))
            {
              List params = new Vector();
              params.add(((Element) fieldSpec.getParentNode())
                  .getAttribute("Name"));
              params.add(fieldSpec.getAttribute("Name"));
              throw new XException(Constants.LOCATION_INTERN,
                  Constants.LAYER_PROTOCOL,
                  Constants.PACKAGE_PROTOCOL_RECORDS, "107",
                  params);
            } // if (!decimalPoint.equals("dot"))
            decPointPos = value.indexOf(decimalP);
          } // if (decimalPoint!=null && decimalPoint.length()>0)

          // Check digits
          int zeroBegin = -1;
          int zeroEnd = value.length();
          boolean onlyZeros = true;
          if (decPointPos > -1)
          { // Check digits before decimal point
            for (int i = 0; i < decPointPos; i++)
            {
              if (!Character.isDigit(value.charAt(i)))
              {
                List params = new Vector();
                params
                    .add(((Element) fieldSpec
                        .getParentNode())
                        .getAttribute("Name"));
                params.add(fieldSpec.getAttribute("Name"));
                params.add("?");
                throw new XException(Constants.LOCATION_INTERN,
                    Constants.LAYER_PROTOCOL,
                    Constants.PACKAGE_PROTOCOL_RECORDS,
                    "108", params);
              } // if
              // (!Character.isDigit(valueWithoutSign.charAt(i)))
              if (onlyZeros && value.charAt(i) == '0')
                zeroBegin = i;
              else
                onlyZeros = false;
            } // for (int i=0; i<decPointPos; i++)
            // Check digits behind decimal point
            onlyZeros = true;
            for (int i = value.length() - 1; i > decPointPos; i--)
            {
              if (!Character.isDigit(value.charAt(i)))
              {
                List params = new Vector();
                params
                    .add(((Element) fieldSpec
                        .getParentNode())
                        .getAttribute("Name"));
                params.add(fieldSpec.getAttribute("Name"));
                params.add("?");
                throw new XException(Constants.LOCATION_INTERN,
                    Constants.LAYER_PROTOCOL,
                    Constants.PACKAGE_PROTOCOL_RECORDS,
                    "108", params);
              } // if
              // (!Character.isDigit(valueWithoutSign.charAt(i)))
              if (onlyZeros && value.charAt(i) == '0')
                zeroEnd = i;
              else
                onlyZeros = false;
            } // for (int i=valueWithoutSign.length()-1;
            // i>decPointPos; i--)
          } // then (decPointPos>-1)
          else
            // no decimal point
            for (int i = 0; i < value.length(); i++)
            {
              if (!Character.isDigit(value.charAt(i)))
              {
                List params = new Vector();
                params
                    .add(((Element) fieldSpec
                        .getParentNode())
                        .getAttribute("Name"));
                params.add(fieldSpec.getAttribute("Name"));
                params.add("?");
                params.add(value);
                throw new XException(Constants.LOCATION_INTERN,
                    Constants.LAYER_PROTOCOL,
                    Constants.PACKAGE_PROTOCOL_RECORDS,
                    "108", params);
              } // if
              // (!Character.isDigit(valueWithoutSign.charAt(i)))
              if (onlyZeros && value.charAt(i) == '0')
                zeroBegin = i;
              else
                onlyZeros = false;
            } // for (int i=0; i<valueWithoutSign.length(); i++)

          String valueWithoutSignZeros = value.substring(
              zeroBegin + 1, zeroEnd);
          int valueWithoutSignZerosLength = valueWithoutSignZeros
              .length();
          byte[] valueWithoutSignZerosBytes = null;
          if (interfaceContentClass == Constants.IFCONTENTCLASS_BYTEARRAYLIST)
          {
            valueWithoutSignZerosBytes = byteArrayConverter
                .stringToByteArray(value);
            valueWithoutSignZerosLength = valueWithoutSignZerosBytes.length;
            if (valueWithoutSignZerosLength > length - start)
            { // Too long - even if zeros are deleted.
              List params = new Vector();
              params.add(((Element) fieldSpec.getParentNode())
                  .getAttribute("Name"));
              params.add(fieldSpec.getAttribute("Name"));
              params.add(value);
              throw new XException(Constants.LOCATION_INTERN,
                  Constants.LAYER_PROTOCOL,
                  Constants.PACKAGE_PROTOCOL_RECORDS, "131",
                  params);
            } // if (valueWithoutSignZerosLength > length - start)
            byte[] zero = byteArrayConverter.stringToByteArray("0");
            if (decPointPos > -1)
            {
              int offset = pos + start;
              for (int i = 0; i < valueWithoutSignZerosLength; i++)
                ((byte[]) buffer)[offset + i] = valueWithoutSignZerosBytes[i];
              offset += valueWithoutSignZerosLength;
              for (int i = 0; i < (length - start - valueWithoutSignZerosLength)
                  / zero.length; i++)
              {
                for (int j = 0; j < zero.length; j++)
                  ((byte[]) buffer)[offset + j] = zero[j];
                offset += zero.length;
              }
              for (int i = offset; i < length; i++)
                ((byte[]) buffer)[i] = 0;
            }
            else
            {
              int offset = pos + start;
              for (int i = 0; i < (length - start - valueWithoutSignZerosLength)
                  / zero.length; i++)
              {
                for (int j = 0; j < zero.length; j++)
                  ((byte[]) buffer)[offset + j] = zero[j];
                offset += zero.length;
              }
              for (int i = 0; i < valueWithoutSignZerosLength; i++)
                ((byte[]) buffer)[offset + i] = valueWithoutSignZerosBytes[i];
              offset += valueWithoutSignZerosLength;
              for (int i = offset; i < length; i++)
                ((byte[]) buffer)[i] = 0;
            }
          }
          else
          {
            if (zeroEnd - zeroBegin - 1 > length - start)
            {
              List params = new Vector();
              params.add(((Element) fieldSpec.getParentNode())
                  .getAttribute("Name"));
              params.add(fieldSpec.getAttribute("Name"));
              params.add(value);
              throw new XException(Constants.LOCATION_INTERN,
                  Constants.LAYER_PROTOCOL,
                  Constants.PACKAGE_PROTOCOL_RECORDS, "131",
                  params);
            } // if (zeroEnd - zeroBegin - 1 > length - start)
            if (length - start + zeroBegin + 1 < value.length())
              // Delete zeros at the end after the decimal point
              // but only to that extend that the necessary length
              // is achieved by delelting leading zeros.
              value = value.substring(0, length - start
                  + zeroBegin + 1);
            if (zeroBegin > -1)
              // Delete zeros at beginning
              value = value.substring(zeroBegin + 1);
            // Fill in zeros at beginning if necessary
            for (int i = 0; i < length - value.length() - start; i++)
              ((StringBuffer) buffer)
                  .insert(pos + start + i, '0');

            // Put value into buffer - sign is already there.
            ((StringBuffer) buffer).insert(pos + length
                - value.length(), value);
          }
        } // (fieldFormat.equals("num"))
        else if (fieldFormat.equals("date"))
        {
          if (value.length() == 0)
            // Blanks allowed.
            if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
              for (int i = 0; i < length; i++)
                ((StringBuffer) buffer).insert(pos + i, ' ');
            else
              fillByteArray((byte[]) buffer, pos, length, "");
          else
          {
            int valueLength = value.length();
            byte[] valueBytes = null;
            if (interfaceContentClass == Constants.IFCONTENTCLASS_BYTEARRAYLIST)
            {
              valueBytes = byteArrayConverter
                  .stringToByteArray(value);
              valueLength = valueBytes.length;
            }
            if (length != valueLength)
            { // Otherwise length must be correct.
              List params = new Vector();
              params.add(((Element) fieldSpec.getParentNode())
                  .getAttribute("Name"));
              params.add(fieldSpec.getAttribute("Name"));
              params.add(value);
              throw new XException(Constants.LOCATION_INTERN,
                  Constants.LAYER_PROTOCOL,
                  Constants.PACKAGE_PROTOCOL_RECORDS, "138",
                  params);
            }
            if (interfaceContentClass == Constants.IFCONTENTCLASS_STRING)
              ((StringBuffer) buffer).insert(pos, value);
            else
              for (int i = 0; i < length; i++)
                ((byte[]) buffer)[pos + i] = valueBytes[i];
          }
        } // then (fieldFormat.equals("date"))
        else
        {
          List params = new Vector();
          params.add(((Element) fieldSpec.getParentNode())
              .getAttribute("Name"));
          params.add(fieldFormat);
          throw new XException(Constants.LOCATION_INTERN,
              Constants.LAYER_PROTOCOL,
              Constants.PACKAGE_PROTOCOL_RECORDS, "139", params);
        } // else (fieldFormat.equals("date"))
      } // else (fieldFormat.equals("blank"))

      return pos + length;
    } // try
    catch (NumberFormatException e)
    {
      throw new XException(Constants.LOCATION_INTERN,
          Constants.LAYER_PROTOCOL,
          Constants.PACKAGE_PROTOCOL_RECORDS, "0", e);
    } // catch
  } // serializeField(Element fieldSpec,StringBuffer buffer,int pos,Node[]
  // fieldNode)

  /**
   * Method fillByteArray.
   *
   * @param b
   * @param pos
   * @param length
   * @param constValue
   */
  private void fillByteArray(byte[] arr, int pos, int length, String value)
      throws XException
  {
    byte[] fill = byteArrayConverter.stringToByteArray(value, length);
    for (int i = 0; i < length; i++)
      arr[pos + i] = fill[i];
  }

  /**
   * Serializes one record.
   *
   * @param doc
   * @return a byte array containing one record
   */
  public byte[] serializeSingleRecord(Document doc) throws XException
  {
    Element record = doc.getDocumentElement();
    return (byte[]) serializeFieldsAndGroups(record,
        getRecordTypeSpec(record.getNodeName()));
  }

} // RecordTypeSerializer
TOP

Related Classes of net.sf.xbus.protocol.records.RecordTypeSerializer

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.