Package de.desy.tine.structUtils

Source Code of de.desy.tine.structUtils.TStructDescription

/*
* Created on Jan 28, 2005
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package de.desy.tine.structUtils;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;

import de.desy.tine.dataUtils.TDataType;
import de.desy.tine.definitions.TErrorList;
import de.desy.tine.definitions.TFormat;
import de.desy.tine.endianUtils.*;
import de.desy.tine.server.logger.MsgLog;
import de.desy.tine.types.*;

/**
* \internal
*
* This class describes a tagged structure, or rather an array of tagged
* structures. A TStructDescription contains a set of TStructDefinition.Field
* which are referenced by tagName. It also contains an arraySize which
* indicates how often this structure occurs in a sequence. Replaces
* TStruct.StructStruct TODO Rename to TStructArrayDescription?
*
* @author jwlg
* @version 2005-02-01
*/
public class TStructDescription
{
  // add cross-reference back to a registered 'TTaggedStructure'
  private TTaggedStructure tts = null;
  public TTaggedStructure getTaggedStructure() { return tts; }
  public void setTaggedStructure(TTaggedStructure struct) { tts = struct; }
  private LinkedList<String> srvKeyLst = new LinkedList<String>();
  /**
   * @param key is the input key to examine and validate
   * @return null if input is not valid or cannot be made into a valid key,
   * otherwise returns a valid key
   */
  private String makeValidSrvKey(String key)
  {
    if (key == null || key.length() == 0) return null;
    if (!key.startsWith("/")) return null;
    int idx;
    if ((idx=key.indexOf("/", 1)) < 0) return null;
    if (key.indexOf("/",idx+1) > 0)
    {
      String[] parts = key.split("/");
      if (parts.length < 3) return null;
      key = "/"+parts[1]+"/"+parts[2];
    }
    return key;
  }
  public boolean containsSrvKey(String key)
  {
    if (srvKeyLst.size() == 0) return true;
    String srvkey = makeValidSrvKey(key);
    if (srvkey == null) return false;
    return srvKeyLst.contains(srvkey);
  }
  public boolean containsSrvKey(String context,String server)
  {
    if (context == null || context.length() == 0) return false;
    if (server == null || server.length() == 0) return false;
    return containsSrvKey("/"+context+"/"+server);
  }
  public void addSrvKey(String key)
  {
    String srvkey = makeValidSrvKey(key);
    if (srvkey == null) return;
    if (srvKeyLst.size() > 0 && srvKeyLst.contains(srvkey)) return;
    srvKeyLst.add(srvkey);
  }
  public void addSrvKey(String context, String server)
  {
    if (context == null || context.length() == 0) return;
    if (server == null || server.length() == 0) return;
    addSrvKey("/"+context+"/"+server);
  }
  public String getTagDecoration()
  {
    if (srvKeyLst.size() == 0) return "";
    return "@"+srvKeyLst.get(0);
  }
  //
  private String tagName = ""; // structure tag
  private int rawLength = 0; // (packed) network data size in bytes
  private int size = 0; // local structure size -> always identical to rawLength for java
  private int arraySize; // array-of buffer capacity (not relevant in java)
  private ArrayList<Field> myFields = new ArrayList<Field>();
  boolean fieldsComplete = false; // True if all fields are added.
  boolean hasExtendedSpace = false;
  public boolean hasExtendedSpace() { return hasExtendedSpace; }
  /**
   * \internal
   *
   * Describes a field of a tagged structure. Replaces TStruct.StructFormat TODO
   * Document attributes
   */
  public class Field
  {
    int arraySize; /* Number of subsequent occurrences in the structure */
    int format; /* TODO TFormat (short) casted to int intentionally(?) */
    int offset; /* Same as address? */
    int address; // TODO Seems to be unused - always identical to offset
    String name;
    /**
     * Default Constructor. Creates a Field of Format CF_NULL.
     */
    public Field()
    {
      this("",0, TFormat.CF_NULL, 0, 0);
    }
    /**
     * Constructs a Field.
     *
     * @param newSize
     *          The number of following elements of this type.
     * @param newFormat
     *          The format of the field.
     * @param newOffset
     *          The offset.
     * @param newAddress
     *          The address.
     */
    public Field(int newSize, short newFormat, int newOffset, int newAddress)
    {
      this("",newSize,newFormat,newOffset,newAddress);
    }
    public Field(String name, int newSize, short newFormat, int newOffset, int newAddress)
    {
      arraySize = newSize;
      format = (int) newFormat;
      offset = newOffset;
      address = newAddress;
      this.name = name;
    }
    /**
     * @return Returns the address.
     */
    public int getAddress()
    {
      return address;
    }
    /**
     * Sets the address.
     *
     * @param address
     *          The address to set.
     */
    public void setAddress(int address)
    {
      this.address = address;
    }
    /**
     * @return Returns the format.
     */
    public short getFormat()
    {
      return (short) format;
    }
    /**
     * Sets the format.
     *
     * @param format
     *          The format to set.
     */
    public void setFormat(short format)
    {
      this.format = (int) format;
    }
    /**
     * @return Returns the offset.
     */
    public int getOffset()
    {
      return offset;
    }
    public String getName()
    {
      return name;
    }
    /**
     * Sets the offset.
     *
     * @param offset
     *          The offset to set.
     */
    public void setOffset(int offset)
    {
      this.offset = offset;
    }
    /**
     * @return Returns the size.
     */
    public int getArraySize()
    {
      return arraySize;
    }
    /**
     * Sets the size.
     *
     * @param size
     *          The size to set.
     */
    public void setArraySize(int size)
    {
      this.arraySize = size;
    }
  }
  /**
   * Constructs a TStructDescription
   *
   * @param newTagName
   *          Name of the new structure
   */
  public TStructDescription(String newTagName)
  {
    this.tagName = newTagName;
  }
  /**
   * Add a Field
   *
   * @param format
   *          The TFormat as specified in TFormat
   * @param arraySize
   *          The number of sequential occurrences of this field
   * @see TFormat
   */
  public void addField(short format, int arraySize)
  {
    addField("",format,arraySize);
  }
  public void addField(String name, short format, int arraySize)
  {
    if (!fieldsComplete)
    { // TODO Is this necessary?
      Field newField = new Field(name, arraySize, format, this.rawLength, this.rawLength);
      int hsiz = TFormat.getFormatHeaderSize(format);
      int dsiz;
      if (TFormat.isVariableLength(format))
      { // CF_STRING, CF_AIMAGE, CF_ASPECTRUM (and CF_IMAGE)
        if (format == TFormat.CF_IMAGE) arraySize = 1; // special case
        dsiz = arraySize * (hsiz + 8); // 2 int32 values specify the position and offset
        hasExtendedSpace = true;
      }
      else
      { // CF_SPECTRUM is not 'variableLength'
        dsiz = arraySize * TFormat.formatSizeOf(format) + hsiz;
      }
      if (format == TFormat.CF_STRUCT)
      {
        String stag = name.substring(1, name.indexOf('>'));
        dsiz *= TStructRegistry.getSizeInBytes(stag);
        if (dsiz < 0)
        {
          MsgLog.log("addField", "nested structure "+stag+" not properly registered!",TErrorList.invalid_structure_tag,null,0);
          return;
        }
      }
      this.rawLength += dsiz;
      // in java, we're only ever dealing with a byte stream, so
      // size = rawLength = sizeInBytes always
      this.size = this.rawLength;
      myFields.add(newField);
    }
  }
  /**
   * Add a field multiple times.
   *
   * @param num
   *          Multiplicity of the field
   * @param format
   *          The TFormat as specified in TFormat
   * @param arraySize
   *          The number of sequential occurrences of this field
   */
  public void addField(int num, short format, int arraySize)
  {
    for (int i = 0; i < num; i++)
    {
      addField(format, arraySize);
    }
  }
  /**
   * Erases the contained information
   */
  private void clear()
  {
    this.arraySize = 0;
    this.rawLength = 0;
    this.fieldsComplete = false;
    this.size = 0;
    this.myFields.clear();
  }
  /**
   * Clears everything and permits definition of fields. TODO Is this necessary?
   */
  public void beginDefinition()
  {
    clear();
  }
  /**
   * Closes definition of fields. TODO Is this necessary?
   */
  public void endDefinition()
  {
    // addField(TFormat.CF_NULL,1);
    fieldsComplete = true;
  }
  /**
   * @return Returns the number of sequential occurrences of this structure.
   */
  public int getArraySize()
  {
    return arraySize;
  }
  /**
   * Sets the number of sequential occurrences of this structure.
   *
   * @param arraySize
   *          The arraySize to set.
   */
  public void setArraySize(int arraySize)
  {
    this.arraySize = arraySize;
  }
  /**
   * @return Returns the tagName.
   */
  public String getTagName()
  {
    return tagName;
  }
  public String getDecoratedTagName()
  {
    return tagName + getTagDecoration();
  }
  /**
   * @param tagName
   *          The tagName to set.
   */
  public void setTagName(String name)
  {
    this.tagName = name;
  }
  /**
   * @return Returns the rawLength.
   */
  public int getRawLength()
  {
    return rawLength;
  }
  /**
   * @return Returns the registered.
   */
  public boolean isFieldsComplete()
  {
    return fieldsComplete;
  }
  /**
   * @return Returns the size.
   */
  public int getSize()
  {
    return size;
  }
  /**
   * Returns a HasMap of all contained fields. The hash map contains keys of
   * type String and entries of type Field.
   */
  public ArrayList<Field> getFields()
  {
    return myFields;
  }
  /**
   * Returns an iterator over all fields. The iterator refers to an entry of
   * type Field.
   * <P>
   * <B>Note: </B>Don't use the iterator to remove Fields!
   * </P>
   *
   * @return
   */
  public Iterator<Field> getFieldIterator()
  {
    return myFields.iterator();
  }
  public int getNFields()
  {
    return myFields.size();
  }
  public Field getField(int i)
  {
    Field rv = null;
    if ((i >= 0) && (i < myFields.size()))
    {
      rv = (Field) myFields.get(i);
    }
    return rv;
  }
  public Field getField(String field)
  {
    Field rv = null;
    Iterator<Field> f = myFields.iterator();
    while (f.hasNext())
    {
      rv = f.next();
      if (rv.getName().compareToIgnoreCase(field) == 0) break;
    }
    return rv;
  }
  public boolean hasField(String field)
  {
    Iterator<Field> f = myFields.iterator();
    while (f.hasNext()) if (f.next().getName().compareToIgnoreCase(field) == 0) return true;
    return false;
  }
  /**
   * Returns the field sizes and formats in a differently coded form used by
   * de.desy.tine.client.
   *
   * @return LongInt Array containing type/format pairs.
   */
  public INTINT[] toLongIntArray()
  {
    int nFields = myFields.size();
    INTINT[] li = new INTINT[nFields + 1];
    Field currentField;
    for (int i = 0; i < nFields; i++)
    {
      currentField = getField(i);
      li[i] = new INTINT(currentField.getArraySize(), currentField.getFormat() + 512);
    }
    // append terminating NULL
    li[nFields] = new INTINT(size, TFormat.CF_NULL + 512);
    return li;
  }
  public NAME16II[] toNameIntIntArray()
  {
    int nFields = myFields.size();
    NAME16II[] li = new NAME16II[nFields + 1];
    Field currentField;
    for (int i = 0; i < nFields; i++)
    {
      currentField = getField(i);
      li[i] = new NAME16II(currentField.getName(),currentField.getArraySize(), currentField.getFormat() + 512);
    }
    // append terminating NULL
    li[nFields] = new NAME16II("",size, TFormat.CF_NULL + 512);
    return li;
  }
  public NAME64DBLDBL[] toNameDblDblArray()
  {
    int nFields = myFields.size();
    NAME64DBLDBL[] li = new NAME64DBLDBL[nFields + 1];
    Field currentField;
    for (int i = 0; i < nFields; i++)
    {
      currentField = getField(i);
      li[i] = new NAME64DBLDBL(currentField.getName(),currentField.getArraySize(), currentField.getFormat() + 512);
    }
    // append terminating NULL
    li[nFields] = new NAME64DBLDBL("",size, TFormat.CF_NULL + 512);
    return li;
  }
  private static boolean isInside = false;
  private static String tagInside = null;
  /**
   * Converts an array of bytes into a string. This method uses the field
   * descriptions to convert an array of bytes into string using a special
   * format. TODO Describe the special format.
   *
   * @param data
   *          A byte array containing the data
   * @param offset
   *          Offset in the byte array.
   * @return Result of conversion.
   */
  public String convertBytesToString(byte[] data, int offset)
  {
    Field currentField;
    int fmt, len;
    byte[] bstr;
    String tag = null;
    StringBuffer buffer = new StringBuffer();
    try
    {
      ByteArrayInputStream dis = new ByteArrayInputStream(data, offset, this.rawLength);
      DataInputStream ds = new DataInputStream(dis);
      for (int n = 0; n < myFields.size(); n++)
      {
        currentField = getField(n);
        len = currentField.getArraySize();
        fmt = (currentField.getFormat()) % 512;
        if (len > 0)
        {
          if (isInside)
          {
            tag = tagInside + currentField.getName() + "] ->";
          }
          else
          {
            tag = "[" + currentField.getName() + "] ->";
          }
          switch (fmt)
          {
            case TFormat.CF_BYTE:
              buffer.append(tag);
              for (int i = 0; i < len; i++)
              {
                buffer.append(i > 0 ? "," : " ");
                buffer.append(ds.readByte());
              }
              buffer.append("\n");
              break;
            case TFormat.CF_TEXT:
              buffer.append(tag);
              bstr = new byte[len];
              ds.read(bstr, 0, len);
              int nlen;
              for (nlen = 0; nlen < len; nlen++) if (bstr[nlen] == 0) break;
              buffer.append(new String(bstr,0,nlen).trim());
              buffer.append("\n");
              break;
            case TFormat.CF_SHORT:
              buffer.append(tag);
              for (int i = 0; i < len; i++)
              {
                buffer.append(i > 0 ? "," : " ");
                buffer.append(SwapUtil.swapShort(ds.readShort()));
              }
              buffer.append("\n");
              break;
            case TFormat.CF_LONG:
              buffer.append(tag);
              for (int i = 0; i < len; i++)
              {
                buffer.append(i > 0 ? "," : " ");
                buffer.append(SwapUtil.swapInt(ds.readInt()));
              }
              buffer.append("\n");
              break;
            case TFormat.CF_DLONG:
              buffer.append(tag);
              for (int i = 0; i < len; i++)
              {
                buffer.append(i > 0 ? "," : " ");
                buffer.append(SwapUtil.swapLong(ds.readLong()));
              }
              buffer.append("\n");
              break;             
            case TFormat.CF_FLOAT:
              buffer.append(tag);
              for (int i = 0; i < len; i++)
              {
                buffer.append(i > 0 ? "," : " ");
                // avoid NaN !
                buffer.append(SwapUtil.swapFloat(ds.readInt()));
              }
              buffer.append("\n");
              break;
            case TFormat.CF_DOUBLE:
              buffer.append(tag);
              for (int i = 0; i < len; i++)
              {
                buffer.append(i > 0 ? "," : " ");
                // avoid NaN !
                buffer.append(SwapUtil.swapDouble(ds.readLong()));
              }
              buffer.append("\n");
              break;
            case TFormat.CF_STRUCT:
              String nam = currentField.getName();
              String stag = nam.substring(1, nam.indexOf('>'));
              for (int i=0; i<len; i++)
              {
                byte[] sb = new byte[TFormat.formatSizeOf((short)fmt)*TStructRegistry.getSizeInBytes(stag)];
                ds.read(sb);
                isInside = true;
                if (len > 1) tagInside = "[" + currentField.getName()+"("+i+").";
                else tagInside = "[" + currentField.getName()+".";
                buffer.append(TStructRegistry.toString(stag, sb));
                isInside = false;
              }
              break;
            default:
              boolean skip = false;
              int fmtsiz = TFormat.formatSizeOf((short)fmt);
              int hsiz = TFormat.getFormatHeaderSize((short)fmt);
              if (TFormat.isAdjustableLength((short)fmt))
              {
                hsiz += 8;
                fmtsiz = hsiz;
                skip = true;
              }
              buffer.append(tag);
              byte[] b = new byte[len*fmtsiz];
              ds.read(b);
              if (skip)
              {
                buffer.append("variable length format string space unavailable\n");
                break;
              }
              TDataType dt = new TDataType(len,(short)fmt);
              dt.pushBytes(b);
              dt.dCompletionLength = len;
              dt.getData();
              buffer.append(dt.toString());
              break;
             
          } // Type Switch
        } // if len > 0
      } // for
    }
    catch (IOException e)
    {
      e.printStackTrace();
      MsgLog.log("convertBytesToString",e.getMessage(),TErrorList.code_failure,e,0);       
    }
    return buffer.toString();
  }
  /**
   * Overloaded for Convenience.
   *
   * @param data
   * @see convertBytesToString(byte[],int)
   */
  public String convertBytesToString(byte[] data)
  {
    return convertBytesToString(data, 0);
  }
}
TOP

Related Classes of de.desy.tine.structUtils.TStructDescription

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.