From fa8350833707afc82175dc6a119b653e543a489e Mon Sep 17 00:00:00 2001
From: Don Brutzman <brutzman@nps.edu>
Date: Sun, 15 Nov 2020 15:58:13 -0800
Subject: [PATCH] added javadoc to clear warnings

---
 .../dis7/examples/AlphabeticalPduSender.java  |   8 +
 .../EntityStateEntityIdExampleUse.java        |   6 +-
 .../moves/dis7/examples/EspduReceiver.java    |   3 +
 .../moves/dis7/examples/EspduReceiverNIO.java |   3 +
 .../nps/moves/dis7/examples/EspduSender.java  |   9 +-
 .../moves/dis7/examples/EspduSenderNIO.java   |   3 +
 .../moves/dis7/examples/PduListenerSaver.java |   3 +
 .../moves/dis7/examples/PduReaderPlayer.java  |   3 +
 .../dis7/examples/ThreadedNetExample.java     |   3 +
 .../nps/moves/dis7/examples/package-info.java |   6 +
 .../dis7/utilities/CoordinateConversions.java |   2 +
 .../DisThreadedNetworkInterface.java          | 847 +++++++++---------
 ...TrialDisMulticastNetworkingDeprecated.java |  11 +-
 .../moves/dis7/utilities/package-info.java    |   6 +
 .../dis7/utilities/stream/PduPlayer.java      |  19 +-
 .../dis7/utilities/stream/PduRecorder.java    |   8 +-
 .../dis7/utilities/stream/X3dCoordinates.java |  24 +
 .../stream/X3dCreateInterpolators.java        |   2 +
 .../dis7/utilities/stream/package-info.java   |   6 +
 src/edu/nps/moves/spatial/package-info.java   |   6 +
 20 files changed, 557 insertions(+), 421 deletions(-)
 create mode 100644 src/edu/nps/moves/dis7/examples/package-info.java
 create mode 100644 src/edu/nps/moves/dis7/utilities/package-info.java
 create mode 100644 src/edu/nps/moves/dis7/utilities/stream/package-info.java
 create mode 100644 src/edu/nps/moves/spatial/package-info.java

diff --git a/src/edu/nps/moves/dis7/examples/AlphabeticalPduSender.java b/src/edu/nps/moves/dis7/examples/AlphabeticalPduSender.java
index 985b1da260..c7ad7ce61b 100644
--- a/src/edu/nps/moves/dis7/examples/AlphabeticalPduSender.java
+++ b/src/edu/nps/moves/dis7/examples/AlphabeticalPduSender.java
@@ -31,6 +31,10 @@ public class AlphabeticalPduSender
   private int port;
   InetAddress multicastAddress;
 
+  /** Constructor
+     * @param port socket port number
+     * @param multicast multicast address
+     */
   public AlphabeticalPduSender(int port, String multicast)
   {
     try {
@@ -45,6 +49,7 @@ public class AlphabeticalPduSender
     }
   }
 
+  /** Invocable run method for this object */
   public void run()
   {
     try {
@@ -323,6 +328,9 @@ public class AlphabeticalPduSender
     }
   }
 
+  /** Command-line invocation (CLI)
+    * @param args command-line arguments
+    */
   public static void main(String args[])
   {
     AlphabeticalPduSender sender;
diff --git a/src/edu/nps/moves/dis7/examples/EntityStateEntityIdExampleUse.java b/src/edu/nps/moves/dis7/examples/EntityStateEntityIdExampleUse.java
index 6cab74715c..4463022f71 100644
--- a/src/edu/nps/moves/dis7/examples/EntityStateEntityIdExampleUse.java
+++ b/src/edu/nps/moves/dis7/examples/EntityStateEntityIdExampleUse.java
@@ -126,7 +126,11 @@ public class EntityStateEntityIdExampleUse
     // Do something here with the pdu you received
     System.out.println("Received "+pdu.getClass().getSimpleName());
   }
-  
+
+  /** Command-line invocation (CLI)
+    * @param args command-line arguments
+    * @throws java.lang.Exception if fails
+    */
   public static void main(String[] args) throws Exception
   {
       EntityStateEntityIdExampleUse.exampleUse(); // run example showing use
diff --git a/src/edu/nps/moves/dis7/examples/EspduReceiver.java b/src/edu/nps/moves/dis7/examples/EspduReceiver.java
index ec05a3ad1d..60c4a61bf2 100644
--- a/src/edu/nps/moves/dis7/examples/EspduReceiver.java
+++ b/src/edu/nps/moves/dis7/examples/EspduReceiver.java
@@ -28,6 +28,9 @@ import java.util.List;
  */
 public class EspduReceiver
 {
+  /** Command-line invocation (CLI)
+    * @param args command-line arguments
+    */
   public static void main(String args[])
   {
     MulticastSocket socket;
diff --git a/src/edu/nps/moves/dis7/examples/EspduReceiverNIO.java b/src/edu/nps/moves/dis7/examples/EspduReceiverNIO.java
index 307e80d2b4..c1a6c0df09 100644
--- a/src/edu/nps/moves/dis7/examples/EspduReceiverNIO.java
+++ b/src/edu/nps/moves/dis7/examples/EspduReceiverNIO.java
@@ -21,6 +21,9 @@ import java.net.MulticastSocket;
  */
 public class EspduReceiverNIO
 {
+  /** Command-line invocation (CLI)
+    * @param args command-line arguments
+    */
   public static void main(String args[])
   {
     MulticastSocket   socket;
diff --git a/src/edu/nps/moves/dis7/examples/EspduSender.java b/src/edu/nps/moves/dis7/examples/EspduSender.java
index 2acf953010..da12f792fa 100644
--- a/src/edu/nps/moves/dis7/examples/EspduSender.java
+++ b/src/edu/nps/moves/dis7/examples/EspduSender.java
@@ -22,11 +22,18 @@ import java.util.*;
  */
 public class EspduSender
 {
+  /** default value avoids unterminated zombie senders */
   public static final int NUMBER_TO_SEND = 5000;
 
+  /** TCP/IP network modes */
   public enum NetworkMode
   {
-    UNICAST, MULTICAST, BROADCAST
+    /** unicast socket */
+    UNICAST,
+    /** multicast socket */
+    MULTICAST,
+    /** broadcast socket */
+    BROADCAST
   };
 
   /**
diff --git a/src/edu/nps/moves/dis7/examples/EspduSenderNIO.java b/src/edu/nps/moves/dis7/examples/EspduSenderNIO.java
index b986118ad8..20ab58b793 100644
--- a/src/edu/nps/moves/dis7/examples/EspduSenderNIO.java
+++ b/src/edu/nps/moves/dis7/examples/EspduSenderNIO.java
@@ -24,6 +24,9 @@ import java.net.MulticastSocket;
  */
 public class EspduSenderNIO
 {
+  /** Command-line invocation (CLI)
+    * @param args command-line arguments
+    */
   public static void main(String args[])
   {
     MulticastSocket   socket;
diff --git a/src/edu/nps/moves/dis7/examples/PduListenerSaver.java b/src/edu/nps/moves/dis7/examples/PduListenerSaver.java
index 38dc5134d9..9fffe28a41 100644
--- a/src/edu/nps/moves/dis7/examples/PduListenerSaver.java
+++ b/src/edu/nps/moves/dis7/examples/PduListenerSaver.java
@@ -28,6 +28,9 @@ public class PduListenerSaver
     PAUSED;
   }
 
+  /** Command-line invocation (CLI)
+    * @param args command-line arguments
+    */
   public static void main(String[] args)
   {
     String outputDirectoryPath = DEFAULT_OUTPUT_DIRECTORY;
diff --git a/src/edu/nps/moves/dis7/examples/PduReaderPlayer.java b/src/edu/nps/moves/dis7/examples/PduReaderPlayer.java
index 9525e97c4b..28a8d2eaff 100644
--- a/src/edu/nps/moves/dis7/examples/PduReaderPlayer.java
+++ b/src/edu/nps/moves/dis7/examples/PduReaderPlayer.java
@@ -29,6 +29,9 @@ public class PduReaderPlayer
     PAUSED;
   }
 
+  /** Command-line invocation (CLI)
+    * @param args command-line arguments
+    */
   public static void main(String[] args)
   {
     String outDir = DEFAULT_OUTPUTDIR;
diff --git a/src/edu/nps/moves/dis7/examples/ThreadedNetExample.java b/src/edu/nps/moves/dis7/examples/ThreadedNetExample.java
index b2b3975122..ed8315a1e6 100644
--- a/src/edu/nps/moves/dis7/examples/ThreadedNetExample.java
+++ b/src/edu/nps/moves/dis7/examples/ThreadedNetExample.java
@@ -20,6 +20,9 @@ import edu.nps.moves.dis7.utilities.PduFactory;
  */
 public class ThreadedNetExample
 {
+  /** Command-line invocation (CLI)
+    * @param args command-line arguments
+    */
   public static void main(String[] args)
   {
     // Create an instance of DisThreadedNetworkInterface using default port 3000, mcast 225.4.5.6, use other constructor to specific port and ip
diff --git a/src/edu/nps/moves/dis7/examples/package-info.java b/src/edu/nps/moves/dis7/examples/package-info.java
new file mode 100644
index 0000000000..8421454dce
--- /dev/null
+++ b/src/edu/nps/moves/dis7/examples/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Example classes using edu.nps.moves.dis7 library.
+ */
+// https://stackoverflow.com/questions/624422/how-do-i-document-packages-in-java
+
+package edu.nps.moves.dis7.examples;
diff --git a/src/edu/nps/moves/dis7/utilities/CoordinateConversions.java b/src/edu/nps/moves/dis7/utilities/CoordinateConversions.java
index 4ed7996cb6..f13f050a77 100644
--- a/src/edu/nps/moves/dis7/utilities/CoordinateConversions.java
+++ b/src/edu/nps/moves/dis7/utilities/CoordinateConversions.java
@@ -12,7 +12,9 @@ package edu.nps.moves.dis7.utilities;
  */
 public class CoordinateConversions
 {
+    /** conversion factor */
     public static final double RADIANS_TO_DEGREES = 180.0/Math.PI;
+    /** conversion factor */
     public static final double DEGREES_TO_RADIANS = Math.PI/180.0;
     
     private CoordinateConversions()
diff --git a/src/edu/nps/moves/dis7/utilities/DisThreadedNetworkInterface.java b/src/edu/nps/moves/dis7/utilities/DisThreadedNetworkInterface.java
index 3d6f1c9df0..091c9933b1 100644
--- a/src/edu/nps/moves/dis7/utilities/DisThreadedNetworkInterface.java
+++ b/src/edu/nps/moves/dis7/utilities/DisThreadedNetworkInterface.java
@@ -1,407 +1,440 @@
-/**
- * Copyright (c) 2008-2020, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved.
- * This work is provided under a BSD open-source license, see project license.html and license.txt
- */
-package edu.nps.moves.dis7.utilities;
-
-import edu.nps.moves.dis7.pdus.Pdu;
-import edu.nps.moves.dis7.pdus.DisTime;
-import edu.nps.moves.dis7.enumerations.DISPDUType;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-
-import java.io.IOException;
-import java.net.*;
-import java.nio.ByteBuffer;
-import java.util.*;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * This is a thread-safe, multicast DIS network interface class.
- * 
- * @author Mike Bailey, jmbailey@nps.edu
- * @since Jul 29, 2019
- */
-public class DisThreadedNetworkInterface
-{
-  public static String DEFAULT_MULTICAST_ADDRESS = "225.4.5.6";
-  public static int    DEFAULT_DIS_PORT          = 3000;
-  
-  private static final String TRACE_PREFIX = "[" + DisThreadedNetworkInterface.class.getName() + "] ";
-  private             boolean verbose = true;
-  
-  /** Pdu listener interface */
-  public interface PduListener
-  {
-    void incomingPdu(Pdu pdu);
-  }
-
-  /** Raw pdu listener class and interface */
-  public interface RawPduListener
-  {
-    void incomingPdu(ByteArrayBufferAndLength bAndL);
-  }
-  
-  /**
-   * Stores data for further processing
-   */
-  public class ByteArrayBufferAndLength
-  {
-    public byte[] bufferByteArray;
-    public int length;
-
-    /**
-     * Default constructor for data storage
-     * @param bufferByteArray the data buffer to store
-     * @param length the length of the data buffer
-     */
-    public ByteArrayBufferAndLength(byte[] bufferByteArray, int length)
-    {
-      this.bufferByteArray = bufferByteArray;
-      this.length = length;
-    }
-  }
-  
-  /************ Begin class ***************/
-  
-  /** MTU 8192: TODO this has actually been superseded by a larger buffer size, but good enough for now */
-  public static final int MAX_DIS_PDU_SIZE = 8192;
-  
-  /** MTU 1500:  size of an Ethernet frame, common value to avoid packet segmentation */
-  public static final int MAX_TRANSMISSION_UNIT_SIZE = 1500;
-  
-  private int     disPort;
-  private String  multicastAddress;
-  private boolean killed = false;
-  
-  private InetAddress       inetAddress;
-  private InetSocketAddress inetSocket;
-  private NetworkInterface  networkInterface;
-  private DatagramSocket    socket = null;
-
-  /**
-   * Default constructor using default port 3000 and multicast address 225.4.5.6
-   */
-  public DisThreadedNetworkInterface()
-  {
-    this(DEFAULT_MULTICAST_ADDRESS, DEFAULT_DIS_PORT);
-  }
-
-  /**
-   * Constructor
-   * @param multicastGroup the multicast group address to utilize
-   * @param port the multicast port to utilize
-   */
-  public DisThreadedNetworkInterface(String multicastGroup, int port)
-  {
-    disPort = port;
-    multicastAddress = multicastGroup;
-      try {
-          inetAddress = InetAddress.getByName(multicastAddress);
-      } catch (UnknownHostException ex) {
-          Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex);
-      }
-    inetSocket = new InetSocketAddress(inetAddress, disPort);
-    networkInterface = findIpv4Interface();
-    init();
-  }
-
-  /* *********** queues and lists  and public methods ************** */
-  private final List<PduListener> everyTypeListeners = new ArrayList<>();
-  private final Map<DISPDUType, List<PduListener>> typeListeners = new HashMap<>();
-  private final List<RawPduListener> rawListeners = new ArrayList<>();
-  private final LinkedBlockingQueue<Pdu> pdus2send = new LinkedBlockingQueue<>();
-
-  /**
-   * Add a listener to accept only pdus of a given type
-   * @param lis listener instance implementing the RawPduListener interface
-   * @param typ Pdu type
-   */
-  public void addListener(PduListener lis, DISPDUType typ)
-  {
-    if (typ == null)
-      addListener(lis);
-    else {
-      List<PduListener> arLis = typeListeners.get(typ);
-      if (arLis == null) {
-        arLis = new ArrayList<>();
-        typeListeners.put(typ, arLis);
-      }
-      arLis.add(lis);
-    }
-  }
-  
-  /**
-   * Add a listener to accept all pdu types
-   * @param lis listener instance implementing the RawPduListener interface
-   */
-  public void addListener(PduListener lis)
-  {
-    everyTypeListeners.add(lis);
-  }
-
-  /**
-   * Remove previously added listener
-   * @param lis listener instance implementing the RawPduListener interface
-   */
-  public void removeListener(PduListener lis)
-  {
-    everyTypeListeners.remove(lis);
-
-    typeListeners.entrySet().forEach(entry -> {
-      List<PduListener> arLis = entry.getValue();
-      if (arLis.contains(lis))
-        arLis.remove(lis);
-    });
-  }
-  
-  /**
-   * Add a listener to accept pdus of all types in the form of a byte array
-   * @param lis listener instance implementing the RawPduListener interface
-   */
-  public void addRawListener(RawPduListener lis)
-  {
-    rawListeners.add(lis);
-  }
-  
-  /**
-   * Remove previously added raw listener
-   * @param lis listener instance implementing the RawPduListener interface
-   */
-  public void removeRawListener(RawPduListener lis)
-  {
-    rawListeners.remove(lis);
-  }
-  
-  public int getDisPort()
-  {
-    return disPort;
-  }
-
-  public String getMcastGroup()
-  {
-    return multicastAddress;
-  }
-
-  /**
-   * Send the given pdu to the network using the ip and port given to the constructor
-   * @param pdu the pdu to send
-   */
-  public void send(Pdu pdu)
-  {
-    pdus2send.add(pdu);
-  }
-
-  /* *************** networking i/o ************* */
-  private PduFactory pduFactory = new PduFactory();
-
-  private Thread sender;
-  private Thread receiver;
-
-  private void init()
-  {
-    receiver = new Thread(receiveThread, "DisThreadedNetIF receive thread");
-    receiver.setDaemon(true);
-    receiver.setPriority(Thread.NORM_PRIORITY);
-    receiver.start();
-
-    sender = new Thread(sendThread, "DisThreadedNetIF send thread");
-    sender.setDaemon(true);
-    sender.setPriority(Thread.NORM_PRIORITY);
-    sender.start();
-  }
-  
-    private Runnable receiveThread = () -> {
-
-        int counter = 0;
-
-        // The capacity could go up to MAX_DIS_PDU_SIZE, but this should be good for now
-        // The raw listeners will strip off any extra padding and process what is
-        // required
-        ByteBuffer byteBuffer = ByteBuffer.allocate(MAX_TRANSMISSION_UNIT_SIZE);
-        DatagramPacket packet = new DatagramPacket(byteBuffer.array(), byteBuffer.capacity());
-        Pdu pdu;
-
-        while (!killed) { // keep trying on error
-            
-            // If something trips up with the socket, this thread will attempt to
-            // re-establish for both send/receive threads
-            try {
-                
-                // The initial value of the SO_BROADCAST socket option is FALSE
-                socket = new MulticastSocket(getDisPort());
-                ((MulticastSocket)socket).joinGroup(inetSocket, networkInterface);
-
-                while (!killed) {
-
-                    socket.receive(packet); // blocks here waiting for next DIS pdu to be received on multicast IP and specified port
-                    toRawListeners(packet.getData(), packet.getLength());
-
-                    pdu = pduFactory.createPdu(byteBuffer);
-
-                    if (pdu != null)
-                    {
-                        counter++; // TODO experimental, add to generator as a commented-out diagnostic; consider adding diagnostic mode
-                        if (isVerbose())
-                        {
-                            System.out.println(TRACE_PREFIX + counter + ". received " + pdu.getPduType().toString()
-                                                            + " (timestamp " + DisTime.timeStampToString(pdu.getTimestamp())
-                                                            + ", size " + pdu.getMarshalledSize() + " bytes)");
-                            System.out.flush();
-                        }
-                        toListeners(pdu);
-                    }
-                    byteBuffer.clear();
-                }
-            } 
-            catch (IOException ex) {
-                System.err.println(TRACE_PREFIX + "Exception in DisThreadedNetIF receive thread: " + ex.getLocalizedMessage());
-                System.err.println(TRACE_PREFIX + "Retrying new socket in 1 second");
-            } 
-            finally {
-                if (socket != null && !socket.isClosed()) {
-                    try {
-                        ((MulticastSocket)socket).leaveGroup(inetSocket, networkInterface);
-                    } catch (IOException ex) {
-                        Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex);
-                    }
-                    socket.close();
-                    socket = null;
-                }
-            }
-//      if (!killed)
-//        sleep(250);
-        }
-    };
-
-    private final Runnable sendThread = () -> {
-
-        Pdu pdu;
-
-        // The capacity could go up to MAX_DIS_PDU_SIZE, but this should be good for now
-        ByteArrayOutputStream baos   = new ByteArrayOutputStream(MAX_TRANSMISSION_UNIT_SIZE);
-        DataOutputStream      dos    = new DataOutputStream(baos);
-        DatagramPacket        packet = new DatagramPacket(baos.toByteArray(), baos.size(), inetSocket);
-
-        while (!killed) { // keep trying on error
-            try {
-                while (!killed) {
-                    pdu = pdus2send.take();
-
-                    pdu.marshal(dos);
-                    packet.setData(baos.toByteArray());
-                    socket.send(packet);
-
-                    dos.flush();  // immediately force pdu write
-                    baos.reset();
-                }
-            } 
-            catch (Exception ex)
-            {
-                System.err.println(TRACE_PREFIX + "Exception in DisThreadedNetIF send thread: " + ex.getLocalizedMessage());
-            }
-        }
-        try {
-            dos.close();
-        } catch (IOException e) {}
-    };
-
-    private void toListeners(Pdu pdu) {
-        if (everyTypeListeners.isEmpty()) {
-            return;
-        }
-
-        if (pdu != null) {
-            everyTypeListeners.forEach(lis -> lis.incomingPdu(pdu));
-
-            if (typeListeners.isEmpty()) {
-                return;
-            }
-
-            List<PduListener> arLis = typeListeners.get(pdu.getPduType());
-            if (arLis != null) {
-                arLis.forEach(lis -> lis.incomingPdu(pdu));
-            }
-        }
-    }
-  
-  private void toRawListeners(byte[] data, int len)
-  {
-    if(rawListeners.isEmpty())
-      return;
-    
-    ByteArrayBufferAndLength bl = new ByteArrayBufferAndLength(data, len);
-    rawListeners.forEach(lis->lis.incomingPdu(bl));
-  }
-  
-  public void kill()
-  {
-    killed = true;
-  }
-
-  private void sleep(long ms)
-  {
-    try {
-      Thread.sleep(ms);
-    }
-    catch (InterruptedException ex) {}
-  }
-
-    /**
-     * Find proper IPV4 interface
-     *
-     * @return a network interface to use to join a multicast group
-     */
-    public static NetworkInterface findIpv4Interface() {
-        try {
-            Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
-            NetworkInterface nif;
-            Enumeration<InetAddress> addresses;
-            InetAddress addr;
-
-            while (ifaces != null && ifaces.hasMoreElements()) {
-                nif = ifaces.nextElement();
-                if (nif.isUp()) {
-                    addresses = nif.getInetAddresses();
-                    while (addresses.hasMoreElements()) {
-                        addr = addresses.nextElement();
-                        if (addr instanceof Inet4Address && !addr.isLoopbackAddress() && !addr.isLinkLocalAddress()) 
-                        {
-                            System.out.println(TRACE_PREFIX + "Using network interface " + nif.getDisplayName());
-                            return nif;
-                        }
-                    }
-                }
-            }
-        } catch (SocketException ex) {
-            Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex);
-        }
-        return null;
-    }
-
-    /**
-     * @return the verbose
-     */
-    public boolean isVerbose()
-    {
-        return verbose;
-    }
-
-    /**
-     * @param verbose the verbose to set
-     */
-    public void setVerbose(boolean verbose)
-    {
-        this.verbose = verbose;
-    }
-
-    /**
-     * @param disPort the disPort value to set
-     */
-    public void setDisPort(int disPort)
-    {
-        this.disPort = disPort;
-    }
-}
+/**
+ * Copyright (c) 2008-2020, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved.
+ * This work is provided under a BSD open-source license, see project license.html and license.txt
+ */
+package edu.nps.moves.dis7.utilities;
+
+import edu.nps.moves.dis7.pdus.Pdu;
+import edu.nps.moves.dis7.pdus.DisTime;
+import edu.nps.moves.dis7.enumerations.DISPDUType;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+
+import java.io.IOException;
+import java.net.*;
+import java.nio.ByteBuffer;
+import java.util.*;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * This is a thread-safe, multicast DIS network interface class.
+ * 
+ * @author Mike Bailey, jmbailey@nps.edu
+ * @since Jul 29, 2019
+ */
+public class DisThreadedNetworkInterface
+{
+  /** Default value */
+  public static String DEFAULT_MULTICAST_ADDRESS = "225.4.5.6";
+
+  /** Default value */
+  public static int    DEFAULT_DIS_PORT          = 3000;
+  
+  private static final String TRACE_PREFIX = "[" + DisThreadedNetworkInterface.class.getName() + "] ";
+  private             boolean verbose = true;
+  private             boolean verboseIncludesTimestamp = false;
+  
+  /** Pdu listener interface */
+  public interface PduListener
+  {
+      /** Callback method
+       * @param pdu received pdu*/
+    void incomingPdu(Pdu pdu);
+  }
+
+  /** Raw pdu listener class and interface */
+  public interface RawPduListener
+  {
+      /** Callback method
+       * @param bAndL exposed buffer to receive incoming pdu*/
+    void incomingPdu(ByteArrayBufferAndLength bAndL);
+  }
+  
+  /**
+   * Stores data for further processing
+   */
+  public class ByteArrayBufferAndLength
+  {
+    /** Active ByteArray buffer */
+    public byte[] bufferByteArray;
+    /** Active ByteArray buffer length */
+    public int length;
+
+    /**
+     * Default constructor for data storage
+     * @param bufferByteArray the data buffer to store
+     * @param length the length of the data buffer
+     */
+    public ByteArrayBufferAndLength(byte[] bufferByteArray, int length)
+    {
+      this.bufferByteArray = bufferByteArray;
+      this.length = length;
+    }
+  }
+  
+  /************ Begin class ***************/
+  
+  /** MTU 8192: TODO this has actually been superseded by a larger buffer size, but good enough for now */
+  public static final int MAX_DIS_PDU_SIZE = 8192;
+  
+  /** MTU 1500:  size of an Ethernet frame, common value to avoid packet segmentation */
+  public static final int MAX_TRANSMISSION_UNIT_SIZE = 1500;
+  
+  private int     disPort;
+  private String  multicastAddress;
+  private boolean killed = false;
+  
+  private InetAddress       inetAddress;
+  private InetSocketAddress inetSocket;
+  private NetworkInterface  networkInterface;
+  private DatagramSocket    socket = null;
+
+  /**
+   * Default constructor using default port 3000 and multicast address 225.4.5.6
+   */
+  public DisThreadedNetworkInterface()
+  {
+    this(DEFAULT_MULTICAST_ADDRESS, DEFAULT_DIS_PORT);
+  }
+
+  /**
+   * Constructor
+   * @param multicastGroup the multicast group address to utilize
+   * @param port the multicast port to utilize
+   */
+  public DisThreadedNetworkInterface(String multicastGroup, int port)
+  {
+    disPort = port;
+    multicastAddress = multicastGroup;
+      try {
+          inetAddress = InetAddress.getByName(multicastAddress);
+      } catch (UnknownHostException ex) {
+          Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex);
+      }
+    inetSocket = new InetSocketAddress(inetAddress, disPort);
+    networkInterface = findIpv4Interface();
+    init();
+  }
+
+  /* *********** queues and lists  and public methods ************** */
+  private final List<PduListener> everyTypeListeners = new ArrayList<>();
+  private final Map<DISPDUType, List<PduListener>> typeListeners = new HashMap<>();
+  private final List<RawPduListener> rawListeners = new ArrayList<>();
+  private final LinkedBlockingQueue<Pdu> pdus2send = new LinkedBlockingQueue<>();
+
+  /**
+   * Add a listener to accept only pdus of a given type
+   * @param lis listener instance implementing the RawPduListener interface
+   * @param typ Pdu type
+   */
+  public void addListener(PduListener lis, DISPDUType typ)
+  {
+    if (typ == null)
+      addListener(lis);
+    else {
+      List<PduListener> arLis = typeListeners.get(typ);
+      if (arLis == null) {
+        arLis = new ArrayList<>();
+        typeListeners.put(typ, arLis);
+      }
+      arLis.add(lis);
+    }
+  }
+  
+  /**
+   * Add a listener to accept all pdu types
+   * @param lis listener instance implementing the RawPduListener interface
+   */
+  public void addListener(PduListener lis)
+  {
+    everyTypeListeners.add(lis);
+  }
+
+  /**
+   * Remove previously added listener
+   * @param lis listener instance implementing the RawPduListener interface
+   */
+  public void removeListener(PduListener lis)
+  {
+    everyTypeListeners.remove(lis);
+
+    typeListeners.entrySet().forEach(entry -> {
+      List<PduListener> arLis = entry.getValue();
+      if (arLis.contains(lis))
+        arLis.remove(lis);
+    });
+  }
+  
+  /**
+   * Add a listener to accept pdus of all types in the form of a byte array
+   * @param lis listener instance implementing the RawPduListener interface
+   */
+  public void addRawListener(RawPduListener lis)
+  {
+    rawListeners.add(lis);
+  }
+  
+  /**
+   * Remove previously added raw listener
+   * @param lis listener instance implementing the RawPduListener interface
+   */
+  public void removeRawListener(RawPduListener lis)
+  {
+    rawListeners.remove(lis);
+  }
+
+  /** Get current port value
+    * @return current port value */
+  public int getDisPort()
+  {
+    return disPort;
+  }
+
+  /** Get current multicast address value
+    * @return current multicast address value */
+  public String getMcastGroup()
+  {
+    return multicastAddress;
+  }
+
+  /**
+   * Send the given pdu to the network using the ip and port given to the constructor
+   * @param pdu the pdu to send
+   */
+  public void send(Pdu pdu)
+  {
+    pdus2send.add(pdu);
+  }
+
+  /* *************** networking i/o ************* */
+  private PduFactory pduFactory = new PduFactory();
+
+  private Thread sender;
+  private Thread receiver;
+
+  private void init()
+  {
+    receiver = new Thread(receiveThread, "DisThreadedNetIF receive thread");
+    receiver.setDaemon(true);
+    receiver.setPriority(Thread.NORM_PRIORITY);
+    receiver.start();
+
+    sender = new Thread(sendThread, "DisThreadedNetIF send thread");
+    sender.setDaemon(true);
+    sender.setPriority(Thread.NORM_PRIORITY);
+    sender.start();
+  }
+  
+    private Runnable receiveThread = () -> {
+
+        int counter = 0;
+
+        // The capacity could go up to MAX_DIS_PDU_SIZE, but this should be good for now
+        // The raw listeners will strip off any extra padding and process what is
+        // required
+        ByteBuffer byteBuffer = ByteBuffer.allocate(MAX_TRANSMISSION_UNIT_SIZE);
+        DatagramPacket packet = new DatagramPacket(byteBuffer.array(), byteBuffer.capacity());
+        Pdu pdu;
+
+        while (!killed) { // keep trying on error
+            
+            // If something trips up with the socket, this thread will attempt to
+            // re-establish for both send/receive threads
+            try {
+                // The initial value of the SO_BROADCAST socket option is FALSE
+                socket = new MulticastSocket(getDisPort());
+                ((MulticastSocket)socket).joinGroup(inetSocket, networkInterface);
+
+                while (!killed) {
+
+                    socket.receive(packet); // blocks here waiting for next DIS pdu to be received on multicast IP and specified port
+                    toRawListeners(packet.getData(), packet.getLength());
+
+                    pdu = pduFactory.createPdu(byteBuffer);
+
+                    if (pdu != null)
+                    {
+                        counter++; // TODO experimental, add to generator as a commented-out diagnostic; consider adding diagnostic mode
+                        if (isVerbose())
+                        {
+                            String message = TRACE_PREFIX + counter + ". received " + pdu.getPduType().toString();
+                            if (isVerboseIncludesTimestamp())
+                                message += " (timestamp " + DisTime.timeStampToString(pdu.getTimestamp());
+                            message +=", size " + pdu.getMarshalledSize() + " bytes)";
+                            System.out.println(message);
+                            System.out.flush();
+                        }
+                        toListeners(pdu);
+                    }
+                    byteBuffer.clear();
+                }
+            } 
+            catch (IOException ex) {
+                System.err.println(TRACE_PREFIX + "Exception in DisThreadedNetIF receive thread: " + ex.getLocalizedMessage());
+                System.err.println(TRACE_PREFIX + "Retrying new socket in 1 second");
+            } 
+            finally {
+                if (socket != null && !socket.isClosed()) {
+                    try {
+                        ((MulticastSocket)socket).leaveGroup(inetSocket, networkInterface);
+                    } catch (IOException ex) {
+                        Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex);
+                    }
+                    socket.close();
+                    socket = null;
+                }
+            }
+//      if (!killed)
+//        sleep(250);
+        }
+    };
+
+    private final Runnable sendThread = () -> {
+
+        Pdu pdu;
+
+        // The capacity could go up to MAX_DIS_PDU_SIZE, but this should be good for now
+        ByteArrayOutputStream baos   = new ByteArrayOutputStream(MAX_TRANSMISSION_UNIT_SIZE);
+        DataOutputStream      dos    = new DataOutputStream(baos);
+        DatagramPacket        packet = new DatagramPacket(baos.toByteArray(), baos.size(), inetSocket);
+
+        while (!killed) { // keep trying on error
+            try {
+                while (!killed) {
+                    pdu = pdus2send.take();
+
+                    pdu.marshal(dos);
+                    packet.setData(baos.toByteArray());
+                    socket.send(packet);
+
+                    dos.flush();  // immediately force pdu write
+                    baos.reset();
+                }
+            } 
+            catch (Exception ex)
+            {
+                System.err.println(TRACE_PREFIX + "Exception in DisThreadedNetIF send thread: " + ex.getLocalizedMessage());
+            }
+        }
+        try {
+            dos.close();
+        } catch (IOException e) {}
+    };
+
+    private void toListeners(Pdu pdu) {
+        if (everyTypeListeners.isEmpty()) {
+            return;
+        }
+
+        if (pdu != null) {
+            everyTypeListeners.forEach(lis -> lis.incomingPdu(pdu));
+
+            if (typeListeners.isEmpty()) {
+                return;
+            }
+
+            List<PduListener> arLis = typeListeners.get(pdu.getPduType());
+            if (arLis != null) {
+                arLis.forEach(lis -> lis.incomingPdu(pdu));
+            }
+        }
+    }
+  
+  private void toRawListeners(byte[] data, int len)
+  {
+    if(rawListeners.isEmpty())
+      return;
+    
+    ByteArrayBufferAndLength bl = new ByteArrayBufferAndLength(data, len);
+    rawListeners.forEach(lis->lis.incomingPdu(bl));
+  }
+
+  /** Terminate the instance */
+  public void kill()
+  {
+    killed = true;
+  }
+
+  /** Thread sleep for indicated interval */
+  private void sleep(long ms)
+  {
+    try {
+      Thread.sleep(ms);
+    }
+    catch (InterruptedException ex) {}
+  }
+
+    /**
+     * Find proper IPV4 interface
+     *
+     * @return a network interface to use to join a multicast group
+     */
+    public static NetworkInterface findIpv4Interface() {
+        try {
+            Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
+            NetworkInterface nif;
+            Enumeration<InetAddress> addresses;
+            InetAddress addr;
+
+            while (ifaces != null && ifaces.hasMoreElements()) {
+                nif = ifaces.nextElement();
+                if (nif.isUp()) {
+                    addresses = nif.getInetAddresses();
+                    while (addresses.hasMoreElements()) {
+                        addr = addresses.nextElement();
+                        if (addr instanceof Inet4Address && !addr.isLoopbackAddress() && !addr.isLinkLocalAddress()) 
+                        {
+                            System.out.println(TRACE_PREFIX + "Using network interface " + nif.getDisplayName());
+                            return nif;
+                        }
+                    }
+                }
+            }
+        } catch (SocketException ex) {
+            Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        return null;
+    }
+
+    /**
+     * @return the verbose
+     */
+    public boolean isVerbose()
+    {
+        return verbose;
+    }
+
+    /**
+     * @param verbose the verbose to set
+     */
+    public void setVerbose(boolean verbose)
+    {
+        this.verbose = verbose;
+    }
+
+    /**
+     * @return the verboseIncludesTimestamp value
+     */
+    public boolean isVerboseIncludesTimestamp()
+    {
+        return verboseIncludesTimestamp;
+    }
+
+    /**
+     * @param verboseIncludesTimestamp the value to set
+     */
+    public void setVerboseIncludesTimestamp(boolean verboseIncludesTimestamp)
+    {
+        this.verboseIncludesTimestamp = verboseIncludesTimestamp;
+    }
+
+    /**
+     * @param disPort the disPort value to set
+     */
+    public void setDisPort(int disPort)
+    {
+        this.disPort = disPort;
+    }
+}
diff --git a/src/edu/nps/moves/dis7/utilities/TrialDisMulticastNetworkingDeprecated.java b/src/edu/nps/moves/dis7/utilities/TrialDisMulticastNetworkingDeprecated.java
index ecb8166656..dc5fe9842f 100644
--- a/src/edu/nps/moves/dis7/utilities/TrialDisMulticastNetworkingDeprecated.java
+++ b/src/edu/nps/moves/dis7/utilities/TrialDisMulticastNetworkingDeprecated.java
@@ -24,11 +24,13 @@ import java.util.logging.Logger;
 @Deprecated(since="dis7")
 public class TrialDisMulticastNetworkingDeprecated
 {
+  /** deprecated */
   public class ByteArrayBufferAndLength
   {
     public byte[] bufferByteArray;
     public int length;
 
+  /* deprecated do not use */
     public ByteArrayBufferAndLength(byte[] bufferByteArray, int length)
     {
       this.bufferByteArray = bufferByteArray;
@@ -46,11 +48,13 @@ public class TrialDisMulticastNetworkingDeprecated
   private InetSocketAddress group;
   private NetworkInterface ni;
 
+  /* deprecated do not use */
   public TrialDisMulticastNetworkingDeprecated()
   {
     this(DisThreadedNetworkInterface.DEFAULT_DIS_PORT, DisThreadedNetworkInterface.DEFAULT_MULTICAST_ADDRESS);
   }
 
+  /* deprecated do not use */
   public TrialDisMulticastNetworkingDeprecated(int port, String mcastgroup)
   {
     DIS_PORT = port;
@@ -66,16 +70,19 @@ public class TrialDisMulticastNetworkingDeprecated
     dos = new DataOutputStream(baos);
   }
 
+  /* deprecated do not use */
   public int getPort()
   {
     return DIS_PORT;
   }
 
+  /* deprecated do not use */
   public String getIp()
   {
     return MCAST_GROUP;
   }
 
+  /* deprecated do not use */
   public void stop()
   {
     if(rsocket != null) {
@@ -88,7 +95,8 @@ public class TrialDisMulticastNetworkingDeprecated
       ssocket = null;
     }
   }
-  
+
+  /* deprecated do not use */
   public Pdu receivePdu() throws IOException
   {
     PduFactory pduFactory = new PduFactory();
@@ -99,6 +107,7 @@ public class TrialDisMulticastNetworkingDeprecated
   private MulticastSocket rsocket;
   byte buffer[];
   DatagramPacket packet;
+  /* deprecated do not use */
   public ByteArrayBufferAndLength receiveRawPdu() throws IOException
   {
     rsocket = new MulticastSocket(DIS_PORT);
diff --git a/src/edu/nps/moves/dis7/utilities/package-info.java b/src/edu/nps/moves/dis7/utilities/package-info.java
new file mode 100644
index 0000000000..9cf044a2b9
--- /dev/null
+++ b/src/edu/nps/moves/dis7/utilities/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Utility classes supporting edu.nps.moves.dis7 library.
+ */
+// https://stackoverflow.com/questions/624422/how-do-i-document-packages-in-java
+
+package edu.nps.moves.dis7.utilities;
diff --git a/src/edu/nps/moves/dis7/utilities/stream/PduPlayer.java b/src/edu/nps/moves/dis7/utilities/stream/PduPlayer.java
index 921ecd83d7..e83fd6949c 100644
--- a/src/edu/nps/moves/dis7/utilities/stream/PduPlayer.java
+++ b/src/edu/nps/moves/dis7/utilities/stream/PduPlayer.java
@@ -29,6 +29,7 @@ public class PduPlayer {
 
     /** PDU listener interface */
     public interface RawListener {
+        /** callback */
         void receiveBytes(byte[] ba);
     }
     
@@ -37,15 +38,15 @@ public class PduPlayer {
     private int port;
     private Thread thrd;
 
-    static final String ENCODING_BASE64 = "ENCODING_BASE64";
-    static final String ENCODING_PLAINTEXT = "ENCODING_PLAINTEXT";
-    static final String ENCODING_BINARY = "ENCODING_BINARY";  // TODO likely requires different code path
-    static final String ENCODING_XML = "ENCODING_XML";     // TODO, repeat Open-DIS version 4 effort
-    static final String ENCODING_EXI = "ENCODING_EXI";     // TODO, use Exificient or Nagasena libraries
-    static final String ENCODING_JSON = "ENCODING_JSON";    // TODO, repeat Open-DIS version 4 effort
+    static final String ENCODING_BASE64          = "ENCODING_BASE64";
+    static final String ENCODING_PLAINTEXT       = "ENCODING_PLAINTEXT";
+    static final String ENCODING_BINARY          = "ENCODING_BINARY";  // TODO likely requires different code path
+    static final String ENCODING_XML             = "ENCODING_XML";     // TODO, repeat Open-DIS version 4 effort
+    static final String ENCODING_EXI             = "ENCODING_EXI";     // TODO, use Exificient or Nagasena libraries
+    static final String ENCODING_JSON            = "ENCODING_JSON";    // TODO, repeat Open-DIS version 4 effort
+    static final String ENCODING_CDIS            = "ENCODING_CDIS";    // future work based on new SISO standard
     static final String ENCODING_MAK_DATA_LOGGER = "ENCODING_MAK_DATA_LOGGER";        // verbose pretty-print. perhaps output only (MAK format itself is binary)
     static final String ENCODING_WIRESHARK_DATA_LOGGER = "ENCODING_WIRESHARK_DATA_LOGGER"; // 
-    static final String ENCODING_CDIS = "ENCODING_CDIS";    // future work based on new SISO standard
 
     private static String pduLogEncoding = ENCODING_PLAINTEXT; // TODO use Java enumerations, generalize/share across library
 
@@ -392,15 +393,17 @@ public class PduPlayer {
         }
         return returnValue;
     }
-
+    /** Start or resume this instance */
     public void startResume() {
         paused = false;
     }
 
+    /** Stop or pause this instance */
     public void stopPause() {
         paused = true;
     }
 
+    /** End operation of this instance */
     public void end() {
         closer();
     }
diff --git a/src/edu/nps/moves/dis7/utilities/stream/PduRecorder.java b/src/edu/nps/moves/dis7/utilities/stream/PduRecorder.java
index a7d9bb1ce8..f0ab341b95 100644
--- a/src/edu/nps/moves/dis7/utilities/stream/PduRecorder.java
+++ b/src/edu/nps/moves/dis7/utilities/stream/PduRecorder.java
@@ -28,6 +28,7 @@ import org.apache.commons.io.FilenameUtils;
  */
 public class PduRecorder implements PduReceiver
 {
+  /** Character sentinel indicating remainder of line is a comment */
   public static final String COMMENT_MARKER = "#";
   
   static String outputDirectoryPath   = "./pduLog";
@@ -126,17 +127,18 @@ public class PduRecorder implements PduReceiver
     public static void setPduLogEncoding(String newPduLogEncoding) {
         pduLogEncoding = newPduLogEncoding;
     }
-  
+
+  /** Start or resume this instance */
   public void startResume()
   {
     running = true;
   }
-  
+  /** Stop or pause this instance */
   public void stopPause()
   {
     running = false;
   }
-  
+  /** End operation of this instance */
   public File end()
   {
     running = false;
diff --git a/src/edu/nps/moves/dis7/utilities/stream/X3dCoordinates.java b/src/edu/nps/moves/dis7/utilities/stream/X3dCoordinates.java
index 9f64f1c298..d83e7966c6 100644
--- a/src/edu/nps/moves/dis7/utilities/stream/X3dCoordinates.java
+++ b/src/edu/nps/moves/dis7/utilities/stream/X3dCoordinates.java
@@ -38,50 +38,74 @@ public class X3dCoordinates {
         this.theta = theta;
     }
 
+    /** accessor method for angle of rotation
+     * @return current value */
     public double getPhi() {
         return phi;
     }
 
+    /** accessor method to set angle of rotation
+     * @param phi new angle value */
     public void setPhi(double phi) {
         this.phi = phi;
     }
 
+    /** accessor method for angle of rotation
+     * @return current value */
     public double getPsi() {
         return psi;
     }
 
+    /** accessor method to set angle of rotation
+     * @param psi new angle value */
     public void setPsi(double psi) {
         this.psi = psi;
     }
 
+    /** accessor method for angle of rotation
+     * @return current value */
     public double getTheta() {
         return theta;
     }
 
+    /** accessor method to set angle of rotation
+     * @param theta new angle value */
     public void setTheta(double theta) {
         this.theta = theta;
     }
 
+    /** accessor method to get coordinate x value
+      * @return current value */
     public double getX() {
         return x;
     }
 
+    /** accessor method to set coordinate x value
+     * @param x coordinate value to set */
     public void setX(double x) {
         this.x = x;
     }
 
+    /** accessor method to get coordinate y value
+      * @return current value */
     public double getY() {
         return y;
     }
 
+    /** accessor method to set coordinate y value
+     * @param y coordinate value to set */
     public void setY(double y) {
         this.y = y;
     }
 
+    /** accessor method to get coordinate z value
+      * @return current value */
     public double getZ() {
         return z;
     }
 
+    /** accessor method to set coordinate z value
+     * @param z coordinate value to set */
     public void setZ(double z) {
         this.z = z;
     }
diff --git a/src/edu/nps/moves/dis7/utilities/stream/X3dCreateInterpolators.java b/src/edu/nps/moves/dis7/utilities/stream/X3dCreateInterpolators.java
index dc308f2412..3079b02e17 100644
--- a/src/edu/nps/moves/dis7/utilities/stream/X3dCreateInterpolators.java
+++ b/src/edu/nps/moves/dis7/utilities/stream/X3dCreateInterpolators.java
@@ -35,6 +35,8 @@ public class X3dCreateInterpolators {
     private NumberFormat coordinateNumberFormat = NumberFormat.getInstance(new Locale("en", "US"));
 
     // -------------------- End Variables for Position Interpolator
+
+    /** Default Constructor */
     public X3dCreateInterpolators() {
 
         //3 significant digits equals milimeter position accuracy and 0.001 radians = 0.0572963266634555‬ degrees
diff --git a/src/edu/nps/moves/dis7/utilities/stream/package-info.java b/src/edu/nps/moves/dis7/utilities/stream/package-info.java
new file mode 100644
index 0000000000..b1aef3bc3a
--- /dev/null
+++ b/src/edu/nps/moves/dis7/utilities/stream/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Streaming utility classes supporting edu.nps.moves.dis7 library.
+ */
+// https://stackoverflow.com/questions/624422/how-do-i-document-packages-in-java
+
+package edu.nps.moves.dis7.utilities.stream;
diff --git a/src/edu/nps/moves/spatial/package-info.java b/src/edu/nps/moves/spatial/package-info.java
new file mode 100644
index 0000000000..24678d3243
--- /dev/null
+++ b/src/edu/nps/moves/spatial/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Spatial utility classes supporting edu.nps.moves.dis7 library.
+ */
+// https://stackoverflow.com/questions/624422/how-do-i-document-packages-in-java
+
+package edu.nps.moves.spatial;
-- 
GitLab