//=====================================================================
// File:    ABIIndexEntry.java
// Class:   ABIIndexEntry
// Package: AFLPcore
//
// Author:  James J. Benham
// Date:    August 10, 1998
// Contact: james_benham@hmc.edu
// 
// Genographer v1.0 - Computer assisted scoring of gels.
// Copyright (C) 1998  Montana State University
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; version 2
// of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// The GNU General Public License is distributed in the file GPL
//=====================================================================

package AFLPcore;

/**
 * This class represents an index entry in the ABI Lane files, which
 * are produced by extracting lanes with GeneScan 2.0 or later. It contains
 * information from the entry, like the name, the tag, the number of
 * elements contained in the file, and the data or a pointer to the data.
 * If the data size is less than or equal to 4 bytes, 
 * <code>dataOffset</code> will contain the actual data, otherwise, it
 * is an offset into the file which points to the data.
 *
 * <p> The name is converted into a long integer by the constructor so
 * that a single comparison can be made, instead of comparing characters.
 *
 * <p> The format of the file is described more fully in the help files
 * distributed with the program.
 *
 * @see ABILaneFilter
 *
 * @author James J. Benham
 * @version 1.0.0
 * @date August 10, 1998
 */

class ABIIndexEntry
{
  /** The identifying name of this record */
  String name;
  /** The name represented as a single long integer */
  long nameKey;
  /** The number used to distiguish different fields with the same name*/
  long tagNumber;
  /** The number of elements in this record.*/
  long numElements;
  /** The location of the data in the file, or in some cases, the data
   *  itself. See the class description to tell which it is. */
  long dataOffset;
  /** Used to determine if this record should be matched with a specific
   *  tag. */
  boolean matchTag;
  long recLength;


  /**
   * Create a new index entry with the specified name. The names in the 
   * ABI Lane files are four character entries.
   *
   * @param name   the name of the entry, e.g. DATA, or SpNm
   */
  ABIIndexEntry(String name)
  {
    this.name = name;
    nameKey = calculateKey(name);
    tagNumber = 0;
    numElements = 0;
    dataOffset = 0;
    matchTag = false;
    recLength = 0;
  }

  /**
   * Create a new index entry with the specified name and tag. The names
   * in the ABI Lane files are four characters long.
   *
   * @param name   the name of the entry, e.g. DATA, or SpNm
   * @param tag    the identifying number of the field. For example, a 
   *               file can contain up to 12 DATA entries, but each one
   *               has a different tag number.
   */
  ABIIndexEntry(String name, int tag)
  {
    this.name = name;
    nameKey = calculateKey(name);
    tagNumber = tag;
    numElements = 0;
    dataOffset = 0;
    matchTag = true;
    recLength = 0;
  }

  /**
   * Gives a numeric representation of the name, which is unique for the
   * name. It works by taking the byte value for the charachters and
   * packing them together into a long integer. It assumes that the input
   * is only four charachters long. Any length longer will have only the
   * first four bytes stored, and anything shorter will result in 
   * invalid accesses.
   *
   * @param input   the four-character string to convert to an integer.
   *
   * @return  the bytes of the string (1 per character) packed together.
   *
   * @exception ArrayIndexOutOfBounds  if the input is less than four
   *                                   characters.
   */
  long calculateKey(String input)
  {
    byte b[] = input.getBytes();
    long temp = b[0];
    temp = (((temp << 8) | b[1]) << 8) | b[2];
    temp = (temp << 8) | b[3];
    return temp;
  }

  /**
   * Tells whether or not this record should be matched with only a name
   * or with a tag as well.
   * 
   * @return <code>true</code> if the tag should be matched.
   */
  boolean matchTagNumber()
  {
    return matchTag;
  }
}
