package edu.vt.marian.common; import java.io.*; import java.net.*; import java.util.*; /** * The identifier of an object in the MARIAN universe is composed * of class id and instance id. Class id can be regarded as database id and * instance id can be regarded as a unique id in that database. *
NOTE: classID is properly an unsigned 16-bit quantity; instanceID an unsigned * 32-bit. Unfortunately there are no unsigneds in Java, so we use an int for * classID and test the bounds. Properly, we should use a long for instanceID, * but that's a lot of unused bits so we'll use an int and keep our fingers * crossed. * @author Robert France, Jianxin Zhao *
designer(s): Robert France (france@vt.edu) *
implementator(s): Jianxin Zhao (jxzhao@csgrad.cs.vt.edu), Robert France *
finished time: *
known bugs: *
JDK version: 1.1.5 *
side effects: */ public class FullID { /** just for debugging */ protected Debug debug; protected int classID; protected int instanceID; protected final static int MAX_CLASS_ID = 65535; // 2**16 - 1. protected final static int MAX_INSTANCE_ID = 2147483647; // 2**31 (see above). /** return values for methods of this class */ public final static int OK = 0; public final static int BAD_PARAMS = -2; public final static int NULL_STREAM = 7; /** Create an empty full id object where both classID and instanceID have been set to 0 (ABSURD). @param debug used for debugging */ public FullID(Debug debug) { // first initialize data members classID = 0; instanceID = 0; this.debug = debug; } /** Create a full id object with the specified class id and instance id values. @param clID class ID value; @param instID instance ID value; @param debug used for debugging */ public FullID(int clID, int instID, Debug debug) { // first initialize data members classID = clID; instanceID = instID; this.debug = debug; } /** Create a full id object from another one. The created object will have the same class id and instance id as the parameter object. @param id the object to be copied @param debug used for debugging */ public FullID(FullID id, Debug debug) { // first initialize data members this.debug = debug; if (id == null) { debug.dumpTrace("FullID.[constructor 2], parameter id is null"); classID = 0; instanceID = 0; } else // id is not null { classID = id.classID; instanceID = id.instanceID; } } /** Create a full id object from the specified stream. @param br the stream to read out a full id object; @param debug used for debugging */ public FullID(BufferedReader br, Debug debug) { this.debug = debug; classID = 0; instanceID = 0; if (br == null) { debug.dumpTrace("FullID.[BR constructor]: parameter stream is null"); return; } // br is not null, read class id int numLines = 0; try { numLines = Integer.parseInt(br.readLine()); } catch (Exception e0) { debug.dumpTrace("FullID.[BR constructor]: error reading number of lines"); } int i; String s = new String(""); try { for (i = 0; i < numLines; i++) { if (i == 0) { // the beginning s += br.readLine(); } else { // not the first line, so add "\n" between them s += "\n" + br.readLine(); } } } catch (IOException e1) { debug.dumpTrace("FullID.[BR constructor]: error reading class id"); } try { setClassID(Integer.parseInt(s)); } catch (Exception e) { debug.dumpTrace("FullID.[BR constructor]: error parsing Class ID."); return; } // read object id try { numLines = Integer.parseInt(br.readLine()); } catch (Exception e0) { debug.dumpTrace("FullID.[BR constructor]: error reading number of lines"); } s = new String(""); try { for (i = 0; i < numLines; i++) { if (i == 0) { // the beginning s += br.readLine(); } else { // not the first line, so add "\n" between them s += "\n" + br.readLine(); } } } catch (IOException e1) { debug.dumpTrace("FullID.[BR constructor]: error reading instance ID"); } try { setInstanceID(Integer.parseInt(s)); } catch (Exception e) { debug.dumpTrace("FullID.[BR constructor]: error parsing instance ID."); return; } } /** Test whether or not the fullID is valid.
Note: The null object of any class (#classID:0#) is always valid. However, objects with a null classID are not. This is because the null class (CLASS_ABSURD) has no members. @return true / false */ public boolean isValid() { return( (classID > 0) && (classID <= MAX_CLASS_ID) && (instanceID >= 0) && (instanceID <= MAX_INSTANCE_ID) ); } /** Set the class id of this object.
uses the services of class(es): none
@param clID the class id of this object will be set to this value.
@return OK == the value has been set;
BAD_PARAMS == invalid value for clID.
*/
public int setClassID(int clID)
{
if ( (clID < 0) || (clID > MAX_CLASS_ID) )
return BAD_PARAMS;
this.classID = clID;
return OK;
}
/**
Return the class id of this object.
@return the class id of this object as an integer
*/
public int getClassID()
{
return classID;
}
/**
Set the instance id of this object.
@param instID the instance id of this object will be set to this
value
@return OK == the value has been set;
BAD_PARAMS == invalid value for instID.
*/
public int setInstanceID(int instID)
{
if ( (instID < 0) || (instID > MAX_INSTANCE_ID) )
return BAD_PARAMS;
this.instanceID = instID;
return OK;
}
/**
Return the instance id of this object.
@return the instance id of this object as an integer
*/
public int getInstanceID()
{
return instanceID;
}
/**
Tell whether this object has the
same class id and instance id as the parameter object.
@param id the object used to compare with this object
@return true == this object has the same class id and instance id as the
parameter object.
false == this object doesn't have the same class id and instance id
as the parameter object.
*/
public boolean equals(Object o)
{
if (o == null)
{
debug.dumpTrace("FullID.equals(): null parameter.");
return false;
}
if (o instanceof FullID)
{
return( (classID == ((FullID) o).classID) &&
(instanceID == ((FullID) o).instanceID) );
}
debug.dumpTrace("FullID.equals(): parameter not of this class.");
return false;
}
/**
* Generate a hash value suitable for java.util.HashTable.
* @return a positive integer.
*/
public int hashCode()
{
return ( (classID << 16) | instanceID & 0x7FFFFFFF );
// Bit AND replaces symbolic "if (ii<0) ii = -ii;".
}
/**
Pack this into a byte array for compact storage.
@param bos a ByteArrayOutputStream into which to pack this.
@return OK == all jake.
NULL_STREAM == could not write.
*/
public int writePacked(ByteArrayOutputStream bos)
{
DataOutputStream dos = new DataOutputStream(bos);
try
{
dos.writeShort(classID);
dos.writeInt(instanceID);
} catch (Exception e)
{
debug.dumpTrace("Weight.writePacked(): cannot write: " +
e.getMessage());
return NULL_STREAM;
}
return(OK);
}
/**
Read this out of compact storage in a byte array.
@param bis a ByteArrayInputStream from which to unpack this.
@return OK == all jake.
NULL_STREAM == could not read.
*/
public int readPacked(ByteArrayInputStream bis)
{
DataInputStream dis = new DataInputStream(bis);
try
{
classID = dis.readUnsignedShort();
instanceID = dis.readInt();
} catch (Exception e)
{
debug.dumpTrace("Weight.readPacked(): cannot read: " +
e.getMessage());
return NULL_STREAM;
}
return(OK);
}
/**
Convert this to a human-readable string.
@return "@null@" if this is not a valid fullID;
"#classID:instanceID#" if it is.
*/
public String toString()
{
if (! isValid() )
return( new String("@null@") );
else
return( new String ("#" + classID + ":" + instanceID + "#") );
}
/**
Print the content of this object to a specified stream.
@param pw the stream to write this object
@return OK == this object has been write to the stream correctly.
NULL_STREAM == could not read.
*/
public int toStream(PrintWriter pw)
{
if (pw == null)
{
debug.dumpTrace("FullID.toStream(): parameter stream is null");
return NULL_STREAM;
}
// pw is not null
// write class id
String s = Integer.toString(getClassID());
pw.println(1); // ClassID (and InstanceID below) will always be
pw.println(s); // a simple value, thus using only one line.
// write instance id
s = Integer.toString(getInstanceID());
pw.println(1);
pw.println(s);
pw.flush();
return OK;
}
}