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; } }