//-----------------------------------------------------------------------------
// Copyright (c) 1994,1995 Southeastern Universities Research Association,
//                         Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606
//-----------------------------------------------------------------------------
//
// Description:
//      rsvc data object containing multiple dataEntry Object identified
//      by a string tag
//
// Author:  
//      Jie Chen
//      Jefferson Lab HPC Group
//
// Revision History:
//   $Log: rsvcData.java,v $
//   Revision 1.1.1.1  2000/05/23 15:12:50  pal
//   cdev_psi_1.7.2
//
//   Revision 1.1  1999/10/18 17:12:40  chen
//   *** empty log message ***
//
//
//
import java.io.OutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Enumeration;
import java.lang.NumberFormatException;
import rsvcDataTypes;
import rsvcTimeStamp;
import rsvcDataEntry;
import rsvcException;
import rsvcDataOutputStream;

public class rsvcData
{
    // magic number
    public static final int _RSVC_MAGIC_NUM = 0x2c45da2a;
    // this is a hash table holding all data entry objects
    private Hashtable store_;
    
    // no need to put synchronized for memeber functions since
    // the hashtable is thread safe

    /** 
     * Construct an empty rsvcData Object
     */
    public rsvcData ()
    {
	// create a hash table with initial capacity of 1 and load factor 0.25
	// to improve look up time for a data entry
	store_ = new Hashtable (1, (float)0.25);
    }

    /**
     * Construct a rsvcData Object from an existing data object.
     * This is a deep copy.
     */
    public rsvcData (rsvcData data)
    {
	store_ = new Hashtable (1, (float)0.25);

	Object obj;
	rsvcDataEntry temp;
	Enumeration list = data.store_.elements();
	while (list.hasMoreElements()) {
	    obj = list.nextElement ();
	    temp = ((rsvcDataEntry)obj).copy();
	    store_.put (temp.getTag(), temp);
	}
    }
    
    /**
     * Return a duplicated data object: deep copy
     */
    public rsvcData copy ()
    {
	rsvcData data = new rsvcData ();

	Object obj;
	rsvcDataEntry temp;
	Enumeration list = store_.elements();
	while (list.hasMoreElements()) {
	    obj = list.nextElement ();
	    temp = ((rsvcDataEntry)obj).copy();
	    data.store_.put (temp.getTag(), temp);
	}
	return data;
    }

    /**
     * Clean up this data object
     */
    public void remove ()
    {
	store_.clear ();
	// no free individual elements :-(
    }

    /**
     * Remove a dataEntry with tag
     */
    public int remove (String tag)
    {
	if (store_.remove (tag) != null)
	    return 0;
	return -1;
    }

    /**
     * Insert a single byte with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public int insert (String tag, byte data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }

    /**
     * Insert a short value with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public int insert (String tag, short data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }

    /**
     * Insert an integer with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public int insert (String tag, int data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }


    /**
     * Insert a long value with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public int insert (String tag, long data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }

    /**
     * Insert a float value with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public int insert (String tag, float data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }
	    

    /**
     * Insert a double with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public int insert (String tag, double data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }
    
    /**
     * Insert a timestamp with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public  int insert (String tag, rsvcTimeStamp data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }

    /**
     * Insert a String Value with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public  int insert (String tag, String data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }

    /**
     * Insert an array of byte with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public  int insert (String tag, byte[] data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }    

    /**
     * Insert an array of short with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public  int insert (String tag, short[] data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }

    /**
     * Insert an array of integer with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public  int insert (String tag, int[] data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }

    /**
     * Insert an array of long with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public  int insert (String tag, long[] data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }

    /**
     * Insert an array of float with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public  int insert (String tag, float[] data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }    

    /**
     * Insert an array of double with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public  int insert (String tag, double[] data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }    

    /**
     * Insert an array of timestamp with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public  int insert (String tag, rsvcTimeStamp[] data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    } 

    /**
     * Insert an array of string with a tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public  int insert (String tag, String[] data)
    {
	int status = remove (tag);
	rsvcDataEntry entry = new rsvcDataEntry (tag, data);
	store_.put (tag, entry);
	return status;
    }


    /**
     * Insert a data entry item with a given tag. If a data item with the same
     * tag is already there, the previous data is removed and new
     * data is inserted. 
     */
    public  int insert (rsvcDataEntry data)
    {
	int status = remove (data.getTag());
	store_.put (data.getTag(), data);
	return status;
    }

    /**
     * Get a data entry with a tag
     */
    public rsvcDataEntry get (String tag)
    {
	Object obj = store_.get (tag);
	if (obj != null)
	    return (rsvcDataEntry)obj;
	return null;
    }

    /**
     * Find a data entry with a tag
     */
    public  rsvcDataEntry find (String tag)
    {
	Object obj = store_.get (tag);
	if (obj != null)
	    return (rsvcDataEntry)obj;
	return null;
    }    

    /**
     * Find whether this data contains entry with a given tag
     */
    public boolean contains (String tag)
    {
	return store_.containsKey (tag);
    }

    /**
     * Change a data entry tag from old to new.
     * if old tag has no associated data entry, nothing is done
     */
    public void changeTag (String oldtag, String newtag)
    {
	Object obj = store_.remove (oldtag);
	if (obj != null) {
	    rsvcDataEntry data =  (rsvcDataEntry)obj;
	    data.setTag (newtag);
	    store_.put (newtag, data);
	}
    }
    
    /**
     * Copy a data entry with a oldtag to create a new entry with a newtag.
     */
    public void dup (String oldtag, String newtag) throws rsvcException
    {
	if (store_.containsKey (oldtag) != true)
	    throw new rsvcException ("Dup: oldtag has no associated data");
	else if (store_.containsKey (newtag) == true) 
	    throw new rsvcException ("Dup: newtag has associated data");
	else {
	    rsvcDataEntry entry = get (oldtag);
	    rsvcDataEntry newentry = entry.copy();
	    newentry.setTag (newtag);
	    store_.put (newtag, newentry);
	}
    }

    /**
     * Replace all data entries with entries inside the provided data object
     */
    public void replace (rsvcData data)
    {
	Object obj;
	rsvcDataEntry temp;

	Enumeration list = data.store_.elements();
	while (list.hasMoreElements ()) {
	    obj = list.nextElement ();
	    temp = (rsvcDataEntry)obj;
	    if (contains (temp.getTag()))
		insert (temp);
	}
    }

    /**
     * Compare two data objects. Return true if they equal to each other.
     */
    public boolean equals (rsvcData data)
    {
	Object obj0;
	rsvcDataEntry temp0;

	Object obj1;
	rsvcDataEntry temp1;

	Enumeration list0 = data.store_.elements();
	Enumeration list1 = store_.elements();

	int size0 = 0;
	int size1 = 0;
	while (list0.hasMoreElements ()) {
	    obj0 = list0.nextElement ();
	    size0 ++;
	}

	while (list1.hasMoreElements ()) {
	    obj1 = list1.nextElement ();
	    size1 ++;
	}
	if (size0 != size1)
	    return false;
	
	list0 = data.store_.elements ();
	while (list0.hasMoreElements ()) {
	    // for each element, find whether there is an element
	    // in this data
	    obj0 = list0.nextElement ();
	    temp0 = (rsvcDataEntry)obj0;
	    temp1 = get (temp0.getTag());

	    if (temp1 == null || temp0.equals (temp1) == false)
		return false;
	}
	return true;
    }

    /**
     * Return number of data entries inside this object
     */
    public int size ()
    {
	return store_.size();
    }

    /**
     * Return number of valid data entries inside this object
     */
    public int numValidEntries ()
    {
	int count = 0;
	Object obj;
	rsvcDataEntry temp;

	Enumeration list = store_.elements();
	while (list.hasMoreElements ()) {
	    obj = list.nextElement ();
	    temp = (rsvcDataEntry)obj;
	    if (temp.getType() != rsvcDataTypes.RSVC_INVALID)
		count ++;
	}
	return count;
    }

    /**
     * Check whether this data is empty
     */
    public boolean isEmpty ()
    {
	return store_.isEmpty();
    }

    /**
     * Return enumeration of elements
     */
    public Enumeration elements()
    {
	return store_.elements ();
    }

    /**
     * Convert data object to a string representation
     */
    public String toString (String title)
    {
	String result = new String ();
	if (title != null)
	    result = title + "\n";

	Object obj;
	Enumeration list = store_.elements();
	while (list.hasMoreElements()) {
	    obj = list.nextElement ();
	    result += obj.toString ();
	    result += "\n";
	}
	return result;
    }

    /**
     * Convert data object to a string representation
     */
    public String toString ()
    {
	return toString ("Contents: ");
    }
	    
    /**
     * Output contents to standard out
     */
    public void asciiDump ()
    {
	System.out.print ("\nBeginning of display----------------------------\n");
	System.out.print (toString());
	System.out.print ("\nEnd of Display----------------------------------\n");
    }

    /**
     * Calculate stream size of this object
     */
    public int streamSize ()
    {
	rsvcDataEntry tmp = null;
	int           datasize = 0;
	int           i;

	// magic number
	datasize += rsvcDataOutputStream.streamSize (rsvcData._RSVC_MAGIC_NUM);

	// number of elements
	datasize += rsvcDataOutputStream.streamSize (numValidEntries());

	// add size for each valid item
	Enumeration list = store_.elements();
	while (list.hasMoreElements()) {
	    tmp = (rsvcDataEntry)(list.nextElement());
	    // individual data entry size
	    datasize += tmp.streamSize ();
	}
	return datasize;
    }	    

    /**
     * Stream rsvcData into a buffered data output stream
     */
    public void streamOut (OutputStream output) throws IOException
    {
	rsvcDataEntry tmp;
	
	rsvcDataOutputStream writer = new rsvcDataOutputStream (output);

	try{
	    writer.write (rsvcData._RSVC_MAGIC_NUM);
	}catch (IOException e) {
	    throw e;
	}

	try {
	    writer.write (numValidEntries ());
	}catch (IOException e){
	    throw e;
	}

	Enumeration list = store_.elements ();
	while (list.hasMoreElements()) {
	    tmp = (rsvcDataEntry)(list.nextElement());
	    try {
		tmp.streamOut (writer);
	    }catch (IOException e) {
		throw e;
	    }
	}
    }

    /**
     * Stream rsvcData into a buffered data output stream
     */
    public void streamOut (rsvcDataOutputStream writer) throws IOException
    {
	rsvcDataEntry tmp;
	
	try{
	    writer.write (rsvcData._RSVC_MAGIC_NUM);
	}catch (IOException e) {
	    throw e;
	}

	try {
	    writer.write (numValidEntries ());
	}catch (IOException e){
	    throw e;
	}

	Enumeration list = store_.elements ();
	while (list.hasMoreElements()) {
	    tmp = (rsvcDataEntry)(list.nextElement());
	    try {
		tmp.streamOut (writer);
	    }catch (IOException e) {
		throw e;
	    }
	}
    }
	
    /**
     * Take a input data stream and populate this data object
     */
    public void streamIn (InputStream stream) throws IOException
    {
	int i, j;
	// clean out this object first
	remove ();

	// attach input stream
	rsvcDataInputStream input = new rsvcDataInputStream (stream);

	// read magic number first
	int magic;
	try {
	    magic = input.readInt ();
	}catch (IOException e){
	    throw e;
	}

	if (magic != rsvcData._RSVC_MAGIC_NUM) {
	    throw new IOException ("Magic number mismatch");
	}

	// read number of elements
	int count;
	try {
	    count = input.readInt ();
	}catch (IOException e) {
	    throw e;
	}
	// read each data entry
	for (i = 0; i < count; i++) {
	    short  type;
	    short  ndims;
	    int    elems, nelems;
	    String tag = null;
	    rsvcDataEntry de = null;

	    // read tag
	    try {
		tag = input.readString ();
	    }catch (IOException e) {
		throw e;
	    }

	    // read type
	    try {
		type = input.readShort ();
	    }catch (IOException e) {
		throw e;
	    }
	    
	    // read dimension
	    try {
		ndims = input.readShort ();
	    }catch (IOException e) {
		throw e;
	    }	    
	
	    // read number elements
	    try {
		elems = input.readInt ();
	    }catch (IOException e) {
		throw e;
	    }

	    // read data stream compatible to C++ generated stream
	    nelems = elems;
	    if (type != rsvcDataTypes.RSVC_INVALID) {
		if (ndims == 0) 
		    nelems = 1;
		else
		    nelems = elems;
	    }
	    
	    if (type == rsvcDataTypes.RSVC_INVALID) 
		throw new IOException ("Data Entry Type is invalid");
	    else if (type == rsvcDataTypes.RSVC_BYTE) {
		if (nelems == 1) {
		    byte tmp;
		    try {
			tmp = input.readByte ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    byte[] tmp = new byte[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readByte();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_INT16) {
		if (nelems == 1) {
		    short tmp;
		    try {
			tmp = input.readShort ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    short[] tmp = new short[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readShort();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_INT32) {
		if (nelems == 1) {
		    int tmp;
		    try {
			tmp = input.readInt ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    int[] tmp = new int[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readInt();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_LONG) {
		if (nelems == 1) {
		    long tmp;
		    try {
			tmp = input.readLong ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    long[] tmp = new long[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readLong();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_FLOAT) {
		if (nelems == 1) {
		    float tmp;
		    try {
			tmp = input.readFloat ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    float[] tmp = new float[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readFloat();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_DOUBLE) {
		if (nelems == 1) {
		    double tmp;
		    try {
			tmp = input.readDouble ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    double[] tmp = new double[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readDouble();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_TIMESTAMP) {
		if (nelems == 1) {
		    rsvcTimeStamp tmp;
		    try {
			tmp = input.readTimeStamp ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    rsvcTimeStamp[] tmp = new rsvcTimeStamp[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readTimeStamp();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_STRING) {
		if (nelems == 1) {
		    String tmp;
		    try {
			tmp = input.readString ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    String[] tmp = new String[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readString();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    if (de != null) 
		insert (de);	  
	}
	    
    }



    /**
     * Take a input data stream and populate this data object
     */
    public void streamIn (rsvcDataInputStream input) throws IOException
    {
	int i, j;
	// clean out this object first
	remove ();

	// read magic number first
	int magic;
	try {
	    magic = input.readInt ();
	}catch (IOException e){
	    throw e;
	}

	if (magic != rsvcData._RSVC_MAGIC_NUM) {
	    throw new IOException ("Magic number mismatch");
	}

	// read number of elements
	int count;
	try {
	    count = input.readInt ();
	}catch (IOException e) {
	    throw e;
	}
	// read each data entry
	for (i = 0; i < count; i++) {
	    short  type;
	    short  ndims;
	    int    elems, nelems;
	    String tag = null;
	    rsvcDataEntry de = null;

	    // read tag
	    try {
		tag = input.readString ();
	    }catch (IOException e) {
		throw e;
	    }

	    // read type
	    try {
		type = input.readShort ();
	    }catch (IOException e) {
		throw e;
	    }
	    
	    // read dimension
	    try {
		ndims = input.readShort ();
	    }catch (IOException e) {
		throw e;
	    }	    
	
	    // read number elements
	    try {
		elems = input.readInt ();
	    }catch (IOException e) {
		throw e;
	    }

	    // read data stream compatible to C++ generated stream
	    nelems = elems;
	    if (type != rsvcDataTypes.RSVC_INVALID) {
		if (ndims == 0) 
		    nelems = 1;
		else
		    nelems = elems;
	    }
	    
	    if (type == rsvcDataTypes.RSVC_INVALID) 
		throw new IOException ("Data Entry Type is invalid");
	    else if (type == rsvcDataTypes.RSVC_BYTE) {
		if (nelems == 1) {
		    byte tmp;
		    try {
			tmp = input.readByte ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    byte[] tmp = new byte[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readByte();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_INT16) {
		if (nelems == 1) {
		    short tmp;
		    try {
			tmp = input.readShort ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    short[] tmp = new short[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readShort();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_INT32) {
		if (nelems == 1) {
		    int tmp;
		    try {
			tmp = input.readInt ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    int[] tmp = new int[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readInt();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_LONG) {
		if (nelems == 1) {
		    long tmp;
		    try {
			tmp = input.readLong ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    long[] tmp = new long[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readLong();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_FLOAT) {
		if (nelems == 1) {
		    float tmp;
		    try {
			tmp = input.readFloat ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    float[] tmp = new float[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readFloat();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_DOUBLE) {
		if (nelems == 1) {
		    double tmp;
		    try {
			tmp = input.readDouble ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    double[] tmp = new double[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readDouble();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_TIMESTAMP) {
		if (nelems == 1) {
		    rsvcTimeStamp tmp;
		    try {
			tmp = input.readTimeStamp ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    rsvcTimeStamp[] tmp = new rsvcTimeStamp[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readTimeStamp();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    else if (type == rsvcDataTypes.RSVC_STRING) {
		if (nelems == 1) {
		    String tmp;
		    try {
			tmp = input.readString ();
		    }catch (IOException e) {
			throw e;
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
		else {
		    String[] tmp = new String[nelems];
		    for (j = 0; j < nelems; j++) {
			try {
			    tmp[j] = input.readString();
			}
			catch (IOException e) {
			    throw e;
			}
		    }
		    de = new rsvcDataEntry (tag, tmp);
		}
	    }
	    if (de != null) 
		insert (de);	  
	}
	    
    }
}

    
	
