Overview | Package | Class | Tree | Deprecated | Index | Help
PREV CLASS | NEXT CLASS FRAMES  | NO FRAMES
SUMMARY:  INNER | FIELD | CONSTR | METHOD DETAIL:  FIELD | CONSTR | METHOD

Class mil.navy.nps.dis.ProtocolDataUnit

java.lang.Object
  |
  +--mil.navy.nps.dis.PduElement
        |
        +--mil.navy.nps.dis.ProtocolDataUnit
Subclasses:
CollisionPdu, DetonationPdu, EntityStatePdu, FirePdu, SimulationManagementPdu

public abstract class ProtocolDataUnit
extends PduElement
Version:
1.0
Author:
Don McGregor (http://www.stl.nps.navy.mil/~mcgredo)
Location:
http://www.stl.nps.navy.mil/dis-java-vrml/mil/navy/nps/dis/ProtocolDataUnit.java
Hierarchy Diagram:
Summary:
This is an abstract class that actual PDUs inherit from. The ProtocolDataUnit includes the header information that is present in every PDU. Centralizing this information in one class prevents us from having to re-declare it in every class.
Explanation:
This class in turn inherits from PduElement, the abstract class that defines a high-level interface to the "things" that make up a PDU.

I generally declare instance variables to be protected, which means that they are directly accessible from this class and all subclasses. Those who believe in full-jackboot mode will want them declared private, so subclasses can't access them either.

The accessor methods (getProtocolVersion et al) are declared public, so that anyone, including those outside this package, can access them. You should always go through accessor methods when setting values inside an object. Direct access from outside the class can cause mysterious errors that are very hard to track down.

Note that, due to garbage collection, we don't have to worry about the status of orphaned instance variables. For example, this operation will cause memory leaks in C++ or Obj-C:

    protocolVersion = newProtocolVersion;
In C++, this operation would leave an orphaned object; the _old_ object that was held by protocolVersion would have no valid pointers to it, but would still take up memory. With GC, the old, orphaned protocolVersion's memory will be scavanged and returned to use.

Accessor methods return a copy of the thing they're getting, not the actual thing. This prevents violations of encapsulation. If this weren't the case, we might see something like this:

myLength = aPdu.getLength();
myLength.addOne();
this would return another pointer to the same object contained inside of aPdu. addOne() would modify the value inside of aPdu, a violation of encapsulation. So instead we implement getLength() like this:

public UnsignedByte getLength()
{ return (UnsignedByte)length.clone();
}
this creates an identical copy of length and returns that. The calling method can modify that to its heart's content without affecting aPdu. For the same reason, the clone() method should make copies of all the instance variables. Otherwise, the "new" object will have pointers shared with the old object. The clone() operation also helps prevent big dependency meshes for GC.

Serialization should make a call to the superclass before it does its own instance variables.

Note that we do not include the padding variables in the instance variables of objects. Padding is used only in the serialized, external representation of a PDU. The user would have no reason to do anything with padding in an object. Since it is only an artifact of serialization, references to padding are limited to the serialization/deserialization methods.

Also, the length, a field in the header portion, is calculated on the fly rather than saved and set. The header has a fixed length, 18 bytes. To find the size of a PDU, implement the length() method in all the subclasses. This should make a call to super, do any local calculations required, then return the correct number. Your code might look like :

    public int length() {
	return super.length() + 110 + aVector.size * anElement.length();
    }

This adds up the length of the superclass, such as the PDU header, the basic length of the subclass (such as the entity state PDU), and adds the length of any variable number of parameters attached to the PDU.

History:
10Oct96 /Don McGregor /New
15Oct96 /Don McGregor /setter methods with "primitive" types, minor changes as suggested in class.
28Oct96 /Don McGregor /changed length() implementation
17Nov96 /Don McGregor /retrofitted in EntityID object for site, application, entity fields, kept old external interface, added new interface for setting and getting entityID as one object
18Nov96 /Don McGregor /Moved entityID into subclasses of ProtocolDataUnit
10Mar97 /Don McGregor /changes for javadoc
16Apr97 /Don McGregor /PrintStream passed to printValues
8Dec97 /Ronan Fauglas /changes for documentation templates + complements in documentation
11Dec97 /Ronan Fauglas /changed access methods to class variables to "getVariable"
References:
DIS Data Dictionary : PDU Header Record
DIS-Java-VRML Working Group: http://www.stl.nps.navy.mil/dis-java-vrml/
DIS specification : IEEE 1278.1, 4.4.1
See Also:
PduElement, mil.navy.nps.util.SerializationInterface

Field Summary
static boolean DEBUG
          Debugging flag; when set true, turns on verbose diagnostic, statements that prints in the java console.
mil.navy.nps.util.UnsignedByte exerciseID
          Exercise Identifier Field.
mil.navy.nps.util.UnsignedByte pduType
          Type of PDU (entity state, message, etc).
mil.navy.nps.util.UnsignedByte protocolFamily
          Indicates the family of protocols which the PDU belongs to.
mil.navy.nps.util.UnsignedByte protocolVersion
          Current version of the protocol being used.
static int sizeOf
          Constant value--size of a PDU header when written out; sizeOf = 12 bytes.
mil.navy.nps.util.UnsignedInt timestamp
          Time Stamp, either relative or UTC This field shall specify the time which the data in the PDU is valid.
 
Constructor Summary
ProtocolDataUnit()
          Constructor for a default protocol data unit.
 
Method Summary
static void ()
           
java.lang.Object clone()
           
static ProtocolDataUnit datagramToPdu(java.net.DatagramPacket pDatagramPacket)
          Returns a PDU completely read in from the Datagram in parameter.
void deSerialize(java.io.DataInputStream inputStream)
           
mil.navy.nps.util.UnsignedByte getExerciseID()
           
mil.navy.nps.util.UnsignedByte getPduType()
           
mil.navy.nps.util.UnsignedByte getProtocolFamily()
           
mil.navy.nps.util.UnsignedByte getProtocolVersion()
           
mil.navy.nps.util.UnsignedInt getTimestamp()
           
double getVRMLTimestamp()
          Returns the timestamp, INTERPRETED IN THE VRML DEFINITION OF TIME. VRML uses the number of seconds since January 1, 1970, in a double, as the definition of absolute time.
int length()
          Returns the length of the PDU header.
void makeTimestampCurrent()
          This methods sets the Timestamp to the current Time.
java.lang.String PDUName()
          Returns the name of the PDU--eg, Entity State, Fire, Comment, etc-- as a String.
void printValues(int indentLevel, java.io.PrintStream printStream)
           
void serialize(java.io.DataOutputStream outputStream)
           
void setExerciseID(mil.navy.nps.util.UnsignedByte pExerciseID)
           
void setExerciseID(int pExerciseID)
           
void setPduType(mil.navy.nps.util.UnsignedByte pPduType)
           
void setPduType(short pPduType)
           
void setProtocolFamily(mil.navy.nps.util.UnsignedByte pProtocolFamily)
           
void setProtocolFamily(int pProtocolFamily)
           
void setProtocolVersion(mil.navy.nps.util.UnsignedByte pProtocolVersion)
           
void setProtocolVersion(int pProtocolVersion)
           
static void setSimulationStartTime(long pStartTime)
          sets the simulation start time
void setTimestamp(mil.navy.nps.util.UnsignedInt pTimestamp)
           
void setTimestamp(long pTimestamp)
           
 
Methods inherited from class mil.navy.nps.dis.PduElement
clone, deSerialize, length, printValues, serialize
 
Methods inherited from class java.lang.Object
, clone, equals, finalize, getClass, hashCode, notifyAll, notify, toString, wait, wait, wait
 

Field Detail

DEBUG

public static final boolean DEBUG
Debugging flag; when set true, turns on verbose diagnostic, statements that prints in the java console. It is by default set to TRUE.

protocolVersion

protected mil.navy.nps.util.UnsignedByte protocolVersion
Current version of the protocol being used. It is now 2.0 which should be mapped to protocolVersion=5 No default value is set.
References:
DIS Data Dictionary: Protocol Version Field
DIS specification : IEEE 1278.1, 4.4.1.1

exerciseID

protected mil.navy.nps.util.UnsignedByte exerciseID
Exercise Identifier Field. Exercise Identification shall be unique to each exercise being conducted simultaneously on the same communications medium. No default value.
References:
DIS Data Dictionary : Exercise Identifier Field
DIS specification : IEEE 1278.1, 4.4.1.2

pduType

protected mil.navy.nps.util.UnsignedByte pduType
Type of PDU (entity state, message, etc).
References:
DIS Data Dictionary: PDU Type Field
DIS specification : IEEE 1278.1, 4.4.1.3
See Also:
PDUTypeField

protocolFamily

protected mil.navy.nps.util.UnsignedByte protocolFamily
Indicates the family of protocols which the PDU belongs to.
References:
DIS Data Dictionary: Protocol Family Field
DIS specification : IEEE 1278.1, 4.4.1.3

timestamp

protected mil.navy.nps.util.UnsignedInt timestamp
Time Stamp, either relative or UTC This field shall specify the time which the data in the PDU is valid.
References:
DIS Data Dictionary: Time Stamp Field
DIS specification : IEEE 1278.1, 4.4.1
Note:
TimeStamp is initialized on creation of the Pdus.

sizeOf

public static final int sizeOf
Constant value--size of a PDU header when written out; sizeOf = 12 bytes.
Constructor Detail

ProtocolDataUnit

public ProtocolDataUnit()
Constructor for a default protocol data unit. No field is initialized.
Method Detail

static void ()

clone

public java.lang.Object clone()
Overrides:
clone in class PduElement

printValues

public void printValues(int indentLevel,
                        java.io.PrintStream printStream)
Overrides:
printValues in class PduElement

makeTimestampCurrent

public void makeTimestampCurrent()
This methods sets the Timestamp to the current Time.
Explanation:
Sets the timestamp field to a current value. THIS USES THE VRML DEFINITION OF TIME RATHER THAN THE DIS DEFINITION OF TIME. VRML uses a double to hold the number of seconds since January 1, 1970. That takes 64 bits, though, and we have only 32 in the PDU. We get around this, sort of, by adopting the convention of having the start time equal to midnight on the day the simulation started up. With 32 bits, we can run for about 50 days before the number of milliseconds in the field rolls over. When we return the VRML timestamp, we can just add the start time (saved in a class variable) to the timestamp and cast it to a double.

getVRMLTimestamp

public double getVRMLTimestamp()
Returns the timestamp, INTERPRETED IN THE VRML DEFINITION OF TIME. VRML uses the number of seconds since January 1, 1970, in a double, as the definition of absolute time. DIS uses an unsigned int with some absurdly irrelevant definition of time.

setSimulationStartTime

public static void setSimulationStartTime(long pStartTime)
sets the simulation start time

PDUName

public abstract java.lang.String PDUName()
Returns the name of the PDU--eg, Entity State, Fire, Comment, etc-- as a String.
References:
See PDU Name
Returns:
the name of the PDU as a String

getProtocolVersion

public mil.navy.nps.util.UnsignedByte getProtocolVersion()

setProtocolVersion

public void setProtocolVersion(mil.navy.nps.util.UnsignedByte pProtocolVersion)

setProtocolVersion

public void setProtocolVersion(int pProtocolVersion)

getExerciseID

public mil.navy.nps.util.UnsignedByte getExerciseID()

setExerciseID

public void setExerciseID(mil.navy.nps.util.UnsignedByte pExerciseID)

setExerciseID

public void setExerciseID(int pExerciseID)

getPduType

public mil.navy.nps.util.UnsignedByte getPduType()

setPduType

public void setPduType(mil.navy.nps.util.UnsignedByte pPduType)

setPduType

public void setPduType(short pPduType)

getProtocolFamily

public mil.navy.nps.util.UnsignedByte getProtocolFamily()

setProtocolFamily

public void setProtocolFamily(mil.navy.nps.util.UnsignedByte pProtocolFamily)

setProtocolFamily

public void setProtocolFamily(int pProtocolFamily)

getTimestamp

public mil.navy.nps.util.UnsignedInt getTimestamp()

setTimestamp

public void setTimestamp(mil.navy.nps.util.UnsignedInt pTimestamp)

setTimestamp

public void setTimestamp(long pTimestamp)

length

public int length()
Returns the length of the PDU header.
Returns:
the length of the PDU header (currently 12 bytes).
Overrides:
length in class PduElement

serialize

public void serialize(java.io.DataOutputStream outputStream)
Overrides:
serialize in class PduElement

deSerialize

public void deSerialize(java.io.DataInputStream inputStream)
Overrides:
deSerialize in class PduElement

datagramToPdu

public static ProtocolDataUnit datagramToPdu(java.net.DatagramPacket pDatagramPacket)
Returns a PDU completely read in from the Datagram in parameter.
Explanation:
This can't be a constructor, since we don't know what type of object we're going to instantiate before it fires. This is a static (class) method. This gets a bit convoluted, but it makes the external interface nice. We have to decide what type of PDU to instantiate, but we don't know the PDU type until we've read some of it. So we read the first few bytes of the byte array in the datagram packet, and find the PDU type. Then we reset the stream, and tell the new object to deserialize itself. It does this by making a call to super.deserialize as the first executable statement of the deserialize method. This causes the data to be read in the correct order--the data for the PDU header is at the front of the datagram, and that's the first data that's deserialized. Then the subclass deserialize method fires, and that deserializes the next data in the stream, corresponding to that subclass. The process looks something like this:
          ProtocolDataUnit
                 |
                 ^
           EntityStatePDU
  
The deserialize message goes first to the EntityStatePdu. The ESPDU immediately calls the deserialize method in its superclass, ProtocolDataUnit. PDU deserializes the first few instance variables, then returns. The ESPDU then deserializes its ivars. Prints out some information during exectuion if debugging flag is set.
Parameters:
pDatagramPacket - The datagram packet read from the wire
Returns:
the PDU as identified in the datagam (with default initialization)
Throws:
java.lang.RuntimeException - if an IO error occurs.

Overview | Package | Class | Tree | Deprecated | Index | Help
PREV CLASS | NEXT CLASS FRAMES  | NO FRAMES
SUMMARY:  INNER | FIELD | CONSTR | METHOD DETAIL:  FIELD | CONSTR | METHOD