Commit in java/trunk/monitoring-app/src on MAIN
main/java/org/hps/monitoring/gui/ConnectionPanel.java+1729 -> 730
                                /ConnectionStatus.java+1-1729 -> 730
                                /DatePanel.java+5-1729 -> 730
                                /EventButtonsPanel.java+1-1729 -> 730
                                /FieldPanel.java+1-1729 -> 730
                                /FieldsPanel.java+1-1729 -> 730
                                /JobSettings.java+1729 -> 730
                                /MonitoringApplication.java+1-17729 -> 730
                                /RunPanel.java+4-2729 -> 730
                                /SettingsPanel.java+1-1729 -> 730
main/java/org/hps/monitoring/plotting/StripChartBuilder.java+5-2729 -> 730
main/java/org/hps/monitoring/record/EtProcessingStep.java+51added 730
                                   /EventProcessingChain.java+152-286729 -> 730
                                   /EventProcessingStep.java-14729 removed
                                   /EventProcessingThread.java+6-3729 -> 730
                                   /EventProcessor.java+1-1729 -> 730
                                   /EvioProcessingStep.java+158added 730
                                   /LcioProcessingStep.java+114added 730
main/java/org/hps/monitoring/record/composite/CompositeRecord.java+5-5729 -> 730
                                             /CompositeRecordLoop.java+15-16729 -> 730
                                             /CompositeRecordLoopAdapter.java+48-19729 -> 730
                                             /CompositeRecordProcessor.java+31added 730
                                             /CompositeRecordSource.java+5-15729 -> 730
main/java/org/hps/monitoring/record/etevent/EtEventListener.java-51729 removed
                                           /EtEventLoop.java+9-14729 -> 730
main/java/org/hps/monitoring/record/evio/EvioAdapter.java+2729 -> 730
                                        /EvioEventLoop.java-1729 -> 730
                                        /EvioEventProcessor.java+1-1729 -> 730
main/java/org/hps/monitoring/subsys/SystemStatus.java+13729 -> 730
                                   /SystemStatusImpl.java+4-1729 -> 730
test/java/org/hps/monitoring/record/EventProcessingChainTest.java+1-2729 -> 730
                                   /EvioEventProcessingTest.java+1-2729 -> 730
test/java/org/hps/monitoring/record/etevent/EtEventLoopTest.java+2-5729 -> 730
                                           /MultiThreadedEtEventLoopTest.java+2-7729 -> 730
+643-470
4 added + 2 removed + 28 modified, total 34 files
Add comments and code cleanup.

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
ConnectionPanel.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/ConnectionPanel.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/ConnectionPanel.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -19,6 +19,7 @@
 import org.jlab.coda.et.enums.Mode;
 
 /**
+ * Connection settings panel.
  * @author Jeremy McCormick <[log in to unmask]>
  */
 class ConnectionPanel extends FieldsPanel {

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
ConnectionStatus.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/ConnectionStatus.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/ConnectionStatus.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -1,7 +1,7 @@
 package org.hps.monitoring.gui;
 
 /**
- * Connection status setting.
+ * Status of the connection to the ET server from the monitoring client.
  * @author Jeremy McCormick <[log in to unmask]>
  * @version $Id: ConnectionStatus.java,v 1.3 2013/11/05 17:15:04 jeremy Exp $
  */

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
DatePanel.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/DatePanel.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/DatePanel.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -4,7 +4,11 @@
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
-public class DatePanel extends FieldPanel {
+/**
+ * A small JPanel with a date field and a label on its border.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+class DatePanel extends FieldPanel {
     
     private SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss");
     

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
EventButtonsPanel.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/EventButtonsPanel.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/EventButtonsPanel.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -12,7 +12,7 @@
  * This is the panel for controlling the application when it is in pause mode,
  * e.g. to step to the next event, etc.
  */
-public class EventButtonsPanel extends JPanel {
+class EventButtonsPanel extends JPanel {
 
     JButton nextEventsButton;
     JButton pauseButton;

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
FieldPanel.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/FieldPanel.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/FieldPanel.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -11,7 +11,7 @@
  * A panel with a label and a text field.
  * @author Jeremy McCormick <[log in to unmask]>
  */
-public class FieldPanel extends JPanel {
+class FieldPanel extends JPanel {
     
     String fieldName;
     String defaultValue;

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
FieldsPanel.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/FieldsPanel.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/FieldsPanel.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -16,7 +16,7 @@
  * @author Jeremy McCormick <[log in to unmask]>
  * @version $Id: FieldsPanel.java,v 1.3 2013/11/05 17:15:04 jeremy Exp $
  */
-public class FieldsPanel extends JPanel {
+class FieldsPanel extends JPanel {
 
     private int currY = 0;    
     private Insets insets;

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
JobSettings.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/JobSettings.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/JobSettings.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -8,6 +8,7 @@
 import java.util.logging.Level;
 
 /**
+ * The job settings panel.
  * @author Jeremy McCormick <[log in to unmask]>
  * @version $Id: JobSettings.java,v 1.6 2013/10/30 17:05:17 jeremy Exp $
  */

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
MonitoringApplication.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -4,7 +4,6 @@
 import static org.hps.monitoring.gui.MonitoringCommands.CLEAR_LOG_TABLE;
 import static org.hps.monitoring.gui.MonitoringCommands.CONNECT;
 import static org.hps.monitoring.gui.MonitoringCommands.DISCONNECT;
-import static org.hps.monitoring.gui.MonitoringCommands.EDIT_EVENT_REFRESH;
 import static org.hps.monitoring.gui.MonitoringCommands.EXIT;
 import static org.hps.monitoring.gui.MonitoringCommands.LOAD_CONNECTION;
 import static org.hps.monitoring.gui.MonitoringCommands.LOAD_JOB_SETTINGS;
@@ -52,8 +51,6 @@
 import java.net.InetAddress;
 import java.text.SimpleDateFormat;
 import java.util.Date;
-import java.util.Timer;
-import java.util.TimerTask;
 import java.util.Vector;
 import java.util.logging.Handler;
 import java.util.logging.Level;
@@ -92,13 +89,6 @@
  * @author Jeremy McCormick <[log in to unmask]>
  * @version $Id: MonitoringApplication.java,v 1.61 2013/12/10 07:36:40 jeremy Exp $
  */
-// FIXME: The tabs panel isn't filling the full available space even when fill is set to both.
-// TODO: Remove minimum GUI component size settings where they are redundant.
-// TODO: Refactor this class into multiple classes.
-// TODO: Log the messages from all Exceptions.
-// TODO: Capture std err and out and redirect to a text panel within the application.
-// TODO: Report state of event processing at the end of the job in a new GUI component.
-// TODO: Move ET cleanup code to the record.etevent package.
 public class MonitoringApplication extends JFrame implements ActionListener {
 
     // Top-level Swing components.
@@ -122,7 +112,6 @@
     private JMenuItem terminalItem;
     private JMenuItem steeringItem;
     private JMenuItem aidaAutoSaveItem;
-    private JMenuItem saveJobSettingsItem;
     private JMenuItem loadJobSettingsItem;
     private JMenuItem resetJobSettingsItem;
 
@@ -1330,13 +1319,9 @@
         eventProcessing.setEventBuilder(this.eventBuilder);
         eventProcessing.setDetectorName(this.getDetectorName());
         eventProcessing.add(this.jobManager.getDriverExecList());
-        //eventProcessing.add(new EventPanelUpdater(eventPanel));
         eventProcessing.add(runPanel.new RunPanelUpdater());
         eventProcessing.add(new EtSystemStripCharts());
-        eventProcessing.setStopOnEndRun();
-        if (!this.disconnectOnError())
-            eventProcessing.setContinueOnErrors();
-        eventProcessing.configure();
+        eventProcessing.setup();
         eventProcessingThread = new EventProcessingThread(eventProcessing);
     }
 
@@ -1350,7 +1335,6 @@
 
         // Reset the plots panel so that it is empty.
         plotPane.removeAll();
-
     }
     
     /**

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
RunPanel.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/RunPanel.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/RunPanel.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -21,8 +21,8 @@
 public class RunPanel extends JPanel {
 
     FieldPanel runNumberField = new FieldPanel("Run Number", "", 10, false);
-    DatePanel startDateField = new DatePanel("Run Start", "", 20, false); 
-    DatePanel endDateField = new DatePanel("Run End", "", 20, false);
+    DatePanel startDateField = new DatePanel("Run Start", "", 16, false); 
+    DatePanel endDateField = new DatePanel("Run End", "", 16, false);
     FieldPanel lengthField = new FieldPanel("Run Length [sec]", "", 12, false);
     FieldPanel totalEventsField = new FieldPanel("Total Events in Run", "", 14, false);
     FieldPanel elapsedTimeField = new FieldPanel("Elapsed Time [sec]", "", 14, false);;
@@ -114,7 +114,9 @@
         }
         
         public void endJob() {
+            System.out.println("RunPanelUpdater.endJob");
             timer.cancel();
+            timer.purge();
         }
     }
 }
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
SettingsPanel.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SettingsPanel.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SettingsPanel.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -16,7 +16,7 @@
  * The container for the job and connection settings.
  * @author Jeremy McCormick <[log in to unmask]>
  */
-public class SettingsPanel extends JPanel implements ActionListener {
+class SettingsPanel extends JPanel implements ActionListener {
 
     JTabbedPane tabs;
     JobPanel jobPanel = new JobPanel();

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/plotting
StripChartBuilder.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/plotting/StripChartBuilder.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/plotting/StripChartBuilder.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -39,6 +39,10 @@
     
     /**
      * This should be used when the time period for updating is variable. 
+     * 
+     * To update a chart of this type:     
+     * <code>sensorSeries.add(new Minute(new Date()), newData);</code>
+     * 
      * @param title
      * @param yAxisLabel
      * @param maxAge
@@ -46,8 +50,7 @@
      * @return
      */
     /* 
-    To update chart of this type:     
-    sensorSeries.add(new Minute(new Date()), newData);
+
     */
     // TODO: test case
     public static JFreeChart createTimeSeriesChart(String title, String yAxisLabel, int maxAge, int maxCount, int rangeSize) {

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record
EtProcessingStep.java added at 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EtProcessingStep.java	                        (rev 0)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EtProcessingStep.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -0,0 +1,51 @@
+package org.hps.monitoring.record;
+
+import static org.freehep.record.loop.RecordLoop.Command.NEXT;
+
+import org.freehep.record.loop.RecordLoop.Command;
+import org.freehep.record.source.NoSuchRecordException;
+import org.hps.monitoring.record.composite.CompositeRecord;
+import org.hps.monitoring.record.composite.CompositeRecordProcessor;
+import org.hps.monitoring.record.etevent.EtEventLoop;
+import org.jlab.coda.et.EtEvent;
+
+ /**
+  * ET processing step to load an <tt>EtEvent</tt> from the ET ring.
+  */
+class EtProcessingStep extends CompositeRecordProcessor {
+ 
+    EtEventLoop loop = new EtEventLoop();
+    
+    EtProcessingStep() {
+    }
+    
+    EtEventLoop getLoop() {
+        return loop;
+    }
+    
+    public void startJob() {        
+        if (loop == null)
+            throw new RuntimeException();
+    }
+    
+    public void processEvent(CompositeRecord record) throws Exception {
+            
+        // Load the next EtEvent, which calls getEvents() on the ET connection
+        // and feeds records to any loop listeners like status monitors.
+        loop.execute(NEXT);
+            
+        // Get the current EtEvent from the loop, which should have been cached.
+        EtEvent nextEtEvent = (EtEvent) loop.getRecordSource().getCurrentRecord();
+            
+        // Failed to read an EtEvent from the ET server.
+        if (nextEtEvent == null)
+            throw new NoSuchRecordException("No current EtEvent is available.");
+            
+        // Update the CompositeRecord with reference to the current EtEvent.
+        record.setEtEvent(nextEtEvent);
+     }
+    
+    public void endJob() {
+        loop.execute(Command.STOP);
+    }
+}
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record
EventProcessingChain.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EventProcessingChain.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EventProcessingChain.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -1,48 +1,32 @@
 package org.hps.monitoring.record;
 
-import static org.freehep.record.loop.RecordLoop.Command.NEXT;
-
-import java.io.File;
 import java.io.IOException;
-import java.io.PrintStream;
-import java.nio.BufferUnderflowException;
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.List;
 
 import org.freehep.record.loop.AbstractLoopListener;
 import org.freehep.record.loop.LoopEvent;
 import org.freehep.record.loop.RecordLoop.Command;
-import org.freehep.record.source.NoSuchRecordException;
+import org.freehep.record.loop.RecordLoop.State;
 import org.freehep.record.source.RecordSource;
-import org.hps.evio.EventConstants;
 import org.hps.evio.LCSimEventBuilder;
-import org.hps.monitoring.record.composite.CompositeRecord;
 import org.hps.monitoring.record.composite.CompositeRecordLoop;
-import org.hps.monitoring.record.etevent.EtEventLoop;
 import org.hps.monitoring.record.etevent.EtEventProcessor;
 import org.hps.monitoring.record.etevent.EtEventSource;
-import org.hps.monitoring.record.evio.EvioEventLoop;
 import org.hps.monitoring.record.evio.EvioEventProcessor;
 import org.hps.monitoring.record.evio.EvioEventQueue;
 import org.hps.monitoring.record.evio.EvioFileSource;
 import org.hps.monitoring.record.lcio.LcioEventQueue;
-import org.jlab.coda.et.EtEvent;
-import org.jlab.coda.jevio.BaseStructure;
-import org.jlab.coda.jevio.EvioEvent;
-import org.jlab.coda.jevio.EvioException;
-import org.jlab.coda.jevio.EvioReader;
-import org.lcsim.event.EventHeader;
 import org.lcsim.util.Driver;
 import org.lcsim.util.loop.LCIOEventSource;
-import org.lcsim.util.loop.LCSimLoop;
 
 /**
  * This class provides a serial implementation of the monitoring event
  * processing chain.  This is accomplished by chaining together implementations 
- * of FreeHep's <tt>RecordLoop</tt>.
+ * of FreeHep's <tt>RecordLoop</tt> via a <tt>CompositeRecordLoop</tt>.  The
+ * processing for each record type is done from a record listener on the 
+ * composite loop.
  * 
- * The processing chain can be configured to execute the ET, EVIO event building, 
+ * The processing chain can be configured to execute the ET, EVIO event building,
  * or LCIO eventing building stages.  The source can be set to an ET ring,
  * EVIO file source, or LCIO file source.  Any number of event processors
  * can be registered with the different loops for processing the different 
@@ -56,7 +40,7 @@
     /**
      * Type of source for events.
      */
-    enum SourceType {
+    public enum SourceType {
         ET_EVENT,
         EVIO_FILE,
         LCIO_FILE
@@ -65,185 +49,200 @@
     /**
      * Processing stages to execute.
      */
-    enum ProcessingStage {
+    public enum ProcessingStage {
         READ_ET_EVENT,
         BUILD_EVIO_EVENT,
         BUILD_LCIO_EVENT
     }
     
-    SourceType sourceType;    
-    ProcessingStage processingStage = ProcessingStage.BUILD_LCIO_EVENT;    
-    PrintStream logStream = System.out;    
-    List<EventProcessingStep> processingSteps = new ArrayList<EventProcessingStep>();    
-    RecordSource recordSource;    
-    EtEventLoop etLoop = new EtEventLoop();
-    EvioEventLoop evioLoop = new EvioEventLoop();
-    LCSimLoop lcsimLoop = new LCSimLoop();
-    CompositeRecordLoop compositeLoop = new CompositeRecordLoop();            
-    EvioEventQueue evioQueue = new EvioEventQueue();
-    LcioEventQueue lcioQueue = new LcioEventQueue();
-    LCSimEventBuilder eventBuilder;        
-    int totalEventsProcessed;
-    String detectorName;
-    boolean stopOnEndRun;
-    boolean continueOnErrors;
-    String steeringResource;
-    File steeringFile;
-    Exception lastException;
-    volatile boolean isDone;
-    volatile boolean paused;
+    private SourceType sourceType = SourceType.ET_EVENT;
+    private ProcessingStage processingStage = ProcessingStage.BUILD_LCIO_EVENT;    
+    private RecordSource recordSource;
+    private LCSimEventBuilder eventBuilder;
+    private int totalEventsProcessed;
+    private String detectorName;
+    private Exception lastException;
+    private boolean done;
+    private boolean paused;
+    private boolean wasSetup;
+    
+    private EtProcessingStep etStep = new EtProcessingStep();
+    private EvioProcessingStep evioStep = new EvioProcessingStep();
+    private LcioProcessingStep lcioStep = new LcioProcessingStep();
+    private CompositeRecordLoop compositeLoop = new CompositeRecordLoop();
         
     /**
      * No argument constructor.  
-     * The setter methods should be used to setup this class.
+     * The setter methods should be used to configure this class.
      */
     public EventProcessingChain() {  
     }
         
-    public void configure() {
+    /**
+     * Setup the event processing chain based on the current configuration.
+     */
+    public void setup() {
         
+        if (wasSetup) {
+            throw new RuntimeException("The EventProcessingChain was already setup.");
+        }
+        
+        // Add this class as a loop listener.
         compositeLoop.addLoopListener(this);
         
+        // Record source must be set by here.
         if (recordSource == null)
             throw new RuntimeException("No record source was set.");
         
+        // Using the ET server for events.
         if (sourceType == SourceType.ET_EVENT) {
-            this.processingSteps.add(new EtProcessingStep());            
+            // Add the ET event processing step.
+            compositeLoop.addProcessor(etStep);
         }
+   
+        // Building EVIO events.
         if (processingStage.ordinal() >= ProcessingStage.BUILD_EVIO_EVENT.ordinal()) {
+            // Using EVIO event source.
             if (sourceType.ordinal() <= SourceType.EVIO_FILE.ordinal()) {
-                this.processingSteps.add(new EvioProcessingStep());
+                // Using ET event source.
+                if (sourceType == SourceType.ET_EVENT) {
+                    // Use dynamic event queue.
+                    evioStep.setEvioEventQueue(new EvioEventQueue());
+                }
+                // Add EVIO processing step.
+                compositeLoop.addProcessor(evioStep);
             }
-            if (sourceType == SourceType.ET_EVENT) {
-                this.evioLoop.setRecordSource(evioQueue);   
-            }
         }
+        
+        // Building LCIO events.
         if (processingStage.ordinal() >= ProcessingStage.BUILD_LCIO_EVENT.ordinal()) {
-            if (this.eventBuilder != null)
-                this.eventBuilder.setDetectorName(detectorName);
-            this.processingSteps.add(new LcioProcessingStep());
+            // Set detector on event builder.
+            if (eventBuilder != null) 
+                eventBuilder.setDetectorName(detectorName);
             if (sourceType.ordinal() != SourceType.LCIO_FILE.ordinal()) {
-                this.lcsimLoop.setRecordSource(lcioQueue);
+                // Use dynamic event queue.
+                lcioStep.setLcioEventQueue(new LcioEventQueue());
             }
+            // Set event builder.
+            lcioStep.setEventBuilder(eventBuilder);
+            // Add LCIO processing step.
+            compositeLoop.addProcessor(lcioStep);
         }
         
-        // Setup the composite loop.
-        compositeLoop.addProcessingSteps(processingSteps);
-        compositeLoop.registerRecordLoop(etLoop);
-        compositeLoop.registerRecordLoop(evioLoop);
-        compositeLoop.registerRecordLoop(lcsimLoop);        
+        wasSetup = true;
     }
     
+    /**
+     * Set the type of source being used.
+     * @param sourceType The type of source.
+     */
     void setSourceType(SourceType sourceType) {
         this.sourceType = sourceType;
     }
         
-    public void setSteeringFile(File steeringFile) {
-        this.steeringFile = steeringFile;
-    }
-    
-    public void setSteeringResource(String steeringResource) {
-        this.steeringResource = steeringResource;
-    }
-    
+    /**
+     * Set the processing stages to execute.
+     * @param processingStage The processing stages to execute.
+     */
     public void setProcessingStage(ProcessingStage processingStage) {
         this.processingStage = processingStage;
     }
             
+    /**
+     * Set the event builder to be used for the EVIO to LCIO conversion.
+     * @param eventBuilder The event builder to use for EVIO to LCIO conversion.
+     */
     public void setEventBuilder(LCSimEventBuilder eventBuilder) {
         this.eventBuilder = eventBuilder;
     }
     
+    /**
+     * Set the record source.
+     * @param recordSource The record source.
+     */
     public void setRecordSource(EtEventSource recordSource) {
         this.recordSource = recordSource;
-        this.etLoop.setRecordSource(recordSource);
+        this.etStep.getLoop().setRecordSource(recordSource);
         this.sourceType = SourceType.ET_EVENT;
     }
     
+    /**
+     * Set an EVIO event source.
+     * @param recordSource The EVIO event source.
+     */
     public void setRecordSource(EvioFileSource recordSource) {
         this.recordSource = recordSource;
-        this.evioLoop.setRecordSource(recordSource);
+        evioStep.getLoop().setRecordSource(recordSource);
         setSourceType(SourceType.EVIO_FILE);
     }
     
+    /**
+     * Set an LCIO event source.
+     * @param recordSource The LCIO event source.
+     */
     public void setRecordSource(LCIOEventSource recordSource) {
         this.recordSource = recordSource;
         try {
-            this.lcsimLoop.setLCIORecordSource(recordSource);
+            lcioStep.getLoop().setLCIORecordSource(recordSource);
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
         setSourceType(SourceType.LCIO_FILE);
     }
     
+    /**
+     * Add a driver to the LCIO loop.
+     * @param driver The Driver to add.
+     */
     public void add(Driver driver) {
-        this.lcsimLoop.add(driver);
+        lcioStep.getLoop().add(driver);
     }
     
+    /**
+     * Add a list of <tt>Drivers</tt> to the LCIO loop.
+     * @param drivers The list of <tt>Drivers</tt> to add.
+     */
     public void add(Collection<Driver> drivers) {
         for (Driver driver : drivers) { 
-            this.lcsimLoop.add(driver);
+            lcioStep.getLoop().add(driver);
         }
     }
     
+    /**
+     * Add a processor of ET events.
+     * @param processor The processor of ET events.
+     */
     public void add(EtEventProcessor processor) {
-        this.etLoop.addEtEventProcessor(processor);
+        etStep.getLoop().addEtEventProcessor(processor);
     }
     
+    /**
+     * Add a processor of EVIO events.
+     * @param processor The processor of EVIO events.
+     */
     public void add(EvioEventProcessor processor) {
-        this.evioLoop.addEvioEventProcessor(processor);
+        evioStep.getLoop().addEvioEventProcessor(processor);
     }
     
+    /**
+     * Set the name of the detector model to use.
+     * @param detectorName The name of the detector model.
+     */
     public void setDetectorName(String detectorName) {
         this.detectorName = detectorName;
     }
-    
-    public void setPrintStream(PrintStream logStream) {
-        this.logStream = logStream;
-    }
-    
-    public void setStopOnEndRun() {
-        this.stopOnEndRun = true;
-    }
-    
-    public void setContinueOnErrors() {
-        this.continueOnErrors = true;
-    }
-    
-    public CompositeRecord getCompositeRecord() {
-        try {
-            return (CompositeRecord) compositeLoop.getRecordSource().getCurrentRecord();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-      
+                   
     /**
-     * Process one event by executing the processing steps.
-     * @throws IOException If some error occurs while processing events.
+     * Resume event processing from pause mode.
      */
-    void processEvent() throws IOException, NoSuchRecordException {
-        for (EventProcessingStep step : this.processingSteps) {
-            step.execute();
-        }
-        ++this.totalEventsProcessed;
-    }
-        
-    /**
-     * This exception occurs when an EVIO end record is encountered
-     * in the event stream and the processing chain is configured
-     * to stop when this occurs.
-     */
-    class EndRunException extends IOException {
-        EndRunException(String message) {
-            super(message);
-        }
-    }
-    
     public void resume() {
         this.paused = false;
     }
     
+    /**
+     * Suspend event processing e.g. when pausing.
+     * @param loopEvent The loop event.
+     */
     public void suspend(LoopEvent loopEvent) {
         if (loopEvent.getException() != null) {
             loopEvent.getException().printStackTrace();
@@ -251,30 +250,50 @@
         }
     }
     
+    /**
+     * Loop over events until processing ends for some reason.
+     */
     public void loop() {
-        while (!isDone) {
+        // Keep looping until the event processing is flagged as done.
+        while (!done) {
+            // Go into loop mode if the system is not paused.
             if (!paused) {
-                // TODO: Add check here for correct loop state.
-                compositeLoop.execute(Command.GO, true);
+                try {
+                    if (compositeLoop.getState() != State.IDLE)
+                        throw new IllegalLoopStateException(compositeLoop.getState());
+                    // Execute GO on the composite loop.
+                    compositeLoop.execute(Command.GO, true);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    // Set the exception.
+                    this.lastException = e;
+                }
                 
                 // When an exception occurs, which can sometimes just be control flow,
                 // the event processing should stop.
                 if (lastException != null) {
                     lastException.printStackTrace();
-                    if (!isDone)
+                    if (!done)
                         // Call finish manually here as the loop was suspended.
                         finish(); 
                 } 
             }
         }
     }
-    
+
+    /**
+     * Pause the event processing.
+     */
     public void pause() {
-        // TODO: Add check here for correct loop state.
+        if (compositeLoop.getState() != State.LOOPING)
+            throw new IllegalLoopStateException(compositeLoop.getState());
         compositeLoop.execute(Command.PAUSE);
         paused = true;
     }
         
+    /**
+     * Finish the event processing.
+     */
     public void finish() {
         // TODO: Add check here for correct loop state.
         try {
@@ -282,11 +301,15 @@
         } catch (Exception e) {
             e.printStackTrace();
         }
-        isDone = true;
+        done = true;
     }    
         
+    /**
+     * Get the next event e.g. while in pause mode.
+     */
     public void next() {
-        // TODO: Add check here for correct loop state.
+        if (compositeLoop.getState() != State.READY)
+            throw new IllegalLoopStateException(compositeLoop.getState());
         compositeLoop.execute(Command.GO_N, 1L, true);
     }
             
@@ -298,170 +321,13 @@
         return this.totalEventsProcessed;
     }
     
-    public boolean isDone() {
-        return isDone;
-    }
-        
     /**
-     * ET processing step to load an <tt>EtEvent</tt> from the ET ring.
+     * Exception thrown if the loop is not in the correct state
+     * when a certain method is called.
      */
-    private class EtProcessingStep implements EventProcessingStep {
-        
-        /**
-         * Load the next <tt>EtEvent</tt>.
-         */
-        public void execute() throws IOException, NoSuchRecordException {
-            
-            // Load the next EtEvent, which calls getEvents() on the ET connection
-            // and feeds records to any loop listeners like status monitors.
-            etLoop.execute(NEXT);
-            
-            // Get the current EtEvent from the loop, which should have been cached.
-            EtEvent nextEtEvent = (EtEvent) etLoop.getRecordSource().getCurrentRecord();
-            
-            // Failed to read an EtEvent from the ET server.
-            if (nextEtEvent == null)
-                //throw new NoSuchRecordException("No current EtEvent is available.");
-                throw new IOException("No current EtEvent is available.");
-            
-            // Update the CompositeRecord with reference to the current EtEvent.
-            getCompositeRecord().setEtEvent(nextEtEvent);
+    class IllegalLoopStateException extends RuntimeException {
+        IllegalLoopStateException(State state) {
+            super("Illegal loop state: " + state);
         }
     }
-    
-    /**
-     * EVIO processing step to build an <tt>EvioEvent</tt> from the <tt>EtEvent</tt>
-     * or load the next <tt>EvioEvent</tt> from a file if using an EVIO file source.
-     */
-    private class EvioProcessingStep implements EventProcessingStep {
-        
-        /**
-         * Load the next <tt>EvioEvent</tt>, either from a record source
-         * or from the <tt>EtEvent</tt> data.
-         */
-        public void execute() throws IOException, NoSuchRecordException {
-            
-            // Handle case of reading from ET system.
-            if (sourceType == SourceType.ET_EVENT) {
-                EvioEvent evioEvent = null;
-                try {
-                    evioEvent = createEvioEvent(getCompositeRecord().getEtEvent());                    
-                    if (evioEvent == null)
-                        throw new IOException("Failed to create EvioEvent from current EtEvent.");
-                    setEventNumber(evioEvent);
-                } catch (EvioException e) {
-                    throw new IOException(e);
-                }
-            
-                // Add EvioEvent to the queue for loop.
-                evioQueue.addRecord(evioEvent);
-            }
-
-            // Process one EvioEvent.
-            evioLoop.execute(NEXT);         
-            EvioEvent nextEvioEvent = (EvioEvent) evioLoop.getRecordSource().getCurrentRecord();
-            
-            // The call to loop did not create a current record.
-            if (nextEvioEvent == null)
-                throw new NoSuchRecordException("No current EVIO event.");
-            
-            getCompositeRecord().setEvioEvent(nextEvioEvent);
-            
-            // Encountered an end of run record.
-            if (EventConstants.isEndEvent(nextEvioEvent))
-                // If stop on end run is enabled, then trigger an exception to end processing.
-                // FIXME: Does this suspend/stop the event loop properly???
-                if (stopOnEndRun)
-                    throw new EndRunException("EVIO end event received, and stop on end run is enabled.");
-        }
-        
-        /**
-         * Create an <tt>EvioEvent</tt> from the current <tt>EtEvent</tt>.
-         * @param etEvent
-         * @return
-         * @throws IOException
-         * @throws EvioException
-         * @throws BufferUnderflowException
-         */
-        private EvioEvent createEvioEvent(EtEvent etEvent) 
-                throws IOException, EvioException, BufferUnderflowException {
-            return (new EvioReader(etEvent.getDataBuffer())).parseNextEvent();
-        }
-        
-        /**
-         * When reading from ET data, the EVIO event number needs to be set manually
-         * from the event ID bank.
-         * @param evioEvent The <tt>EvioEvent</tt> on which to set the event number.
-         */
-        private void setEventNumber(EvioEvent evioEvent) {
-            int eventNumber = -1;
-            if (evioEvent.getChildren() != null) {
-                for (BaseStructure bank : evioEvent.getChildren()) {
-                    if (bank.getHeader().getTag() == EventConstants.EVENTID_BANK_TAG) {
-                        eventNumber = bank.getIntData()[0];
-                        break;
-                    }
-                }
-            }
-            if (eventNumber != -1)
-                evioEvent.setEventNumber(eventNumber);
-        }
-    }
-    
-    /**
-     * Processing step to build an LCIO event from an <tt>EvioEvent</tt>
-     * or load the next event if using a file source.
-     */
-    private class LcioProcessingStep implements EventProcessingStep {
-        
-        /**
-         * Create the next LCIO event either from the EVIO record
-         * or from a direct LCIO file source.
-         */
-        public void execute() throws IOException, NoSuchRecordException {
-
-            // When the loop does not have a direct LCIO file source, 
-            // the events need to be built from the EVIO input.
-            if (sourceType.ordinal() < SourceType.LCIO_FILE.ordinal()) {
-            
-                EvioEvent currentEvioEvent = getCompositeRecord().getEvioEvent();
-                
-                // Set state on LCIO event builder.
-                eventBuilder.readEvioEvent(currentEvioEvent);
-                
-                // The LCIO event will be built if processing an EVIO physics event.
-                if (eventBuilder.isPhysicsEvent(currentEvioEvent)) {
-
-                    // Use the event builder to create the next LCIO event.
-                    EventHeader lcioEvent = eventBuilder.makeLCSimEvent(currentEvioEvent);
-        
-                    // Add LCIO event to the queue.
-                    lcioQueue.addRecord(lcioEvent);
-                } else {
-                    // The LCIO processing ignores non-physics events coming from EVIO.
-                    return;
-                }
-            }
-        
-            // If using an LCIO file source, check for EOF.
-            if (sourceType == SourceType.LCIO_FILE) {
-                if (!lcsimLoop.getRecordSource().hasNext())
-                    throw new NoSuchRecordException("No next LCIO event.");
-            }
-            
-            // Load the next LCIO event.
-            lcsimLoop.execute(NEXT);
-                                   
-            // The last call to the loop did not create a current record.
-            if (lcsimLoop.getRecordSource().getCurrentRecord() == null) {
-                throw new NoSuchRecordException("No current LCIO event.");
-            }
-            
-            // Get the current LCIO event.
-            EventHeader lcioEvent = (EventHeader) lcsimLoop.getRecordSource().getCurrentRecord();
-            
-            // Update the CompositeRecord with referece to the LCIO event.
-            getCompositeRecord().setLcioEvent(lcioEvent);
-        }
-    }
 }
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record
EventProcessingStep.java removed after 729
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EventProcessingStep.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EventProcessingStep.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -1,14 +0,0 @@
-package org.hps.monitoring.record;
-
-import java.io.IOException;
-
-import org.freehep.record.source.NoSuchRecordException;
-
-/**
- * Interface for a single processing step which handles one type of record.
- */
-// FIXME: This could be done by registering record listener's on CompositeLoop
-// which receive and alter the current CompositeRecord.
-public interface EventProcessingStep {    
-    void execute() throws IOException, NoSuchRecordException;    
-}
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record
EventProcessingThread.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EventProcessingThread.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EventProcessingThread.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -19,7 +19,10 @@
     
     @Override
     public void run() {
-        // FIXME: Need to catch event processing errors here!
-        processing.loop();
+        try {
+            processing.loop();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
     }
-}
+}
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record
EventProcessor.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EventProcessor.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EventProcessor.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -23,7 +23,7 @@
      * Process a single event.
      * @param event
      */
-    void processEvent(EventType event);
+    void processEvent(EventType event) throws Exception;
 
     /**
      * End of run action.

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record
EvioProcessingStep.java added at 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EvioProcessingStep.java	                        (rev 0)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EvioProcessingStep.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -0,0 +1,158 @@
+package org.hps.monitoring.record;
+
+import static org.freehep.record.loop.RecordLoop.Command.NEXT;
+
+import java.io.IOException;
+import java.nio.BufferUnderflowException;
+
+import org.freehep.record.loop.RecordLoop.Command;
+import org.freehep.record.source.NoSuchRecordException;
+import org.hps.evio.EventConstants;
+import org.hps.monitoring.record.EventProcessingChain.SourceType;
+import org.hps.monitoring.record.composite.CompositeRecord;
+import org.hps.monitoring.record.composite.CompositeRecordProcessor;
+import org.hps.monitoring.record.evio.EvioEventLoop;
+import org.hps.monitoring.record.evio.EvioEventQueue;
+import org.jlab.coda.et.EtEvent;
+import org.jlab.coda.jevio.BaseStructure;
+import org.jlab.coda.jevio.EvioEvent;
+import org.jlab.coda.jevio.EvioException;
+import org.jlab.coda.jevio.EvioReader;
+
+/**
+ * EVIO processing step to build an <tt>EvioEvent</tt> from the <tt>EtEvent</tt>
+ * or load the next <tt>EvioEvent</tt> from a file if using an EVIO file source.
+ */
+class EvioProcessingStep extends CompositeRecordProcessor {
+   
+    EvioEventLoop loop = new EvioEventLoop();
+    SourceType sourceType;
+    EvioEventQueue evioEventQueue;
+    boolean stopOnEndRun;
+
+    // FIXME: Should this be extending IOException?
+    class EndRunException extends IOException {
+        EndRunException(String message) {
+            super(message);
+        }
+    }
+    
+    /**
+     * Get the <tt>EvioEventLoop</tt> associated with this processing step.
+     * @return The <tt>EvioEventLoop</tt> associated with this processing step.
+     */
+    EvioEventLoop getLoop() {
+        return loop;
+    }
+
+    /**
+     * Set the EVIO event queue.
+     * @param evioEventQueue The EVIO event queue.
+     */
+    void setEvioEventQueue(EvioEventQueue evioEventQueue) {
+        this.evioEventQueue = evioEventQueue;
+        loop.setRecordSource(this.evioEventQueue);
+    }
+    
+    /**
+     * Set whether an end of run record will throw a control Exception.
+     */
+    void setStopOnEndRun() {
+        stopOnEndRun = true;
+    }
+    
+    /**
+     * Set the <tt>EvioEventLoop</tt> for this processing step.
+     * @param loop The <tt>EvioEventLoop</tt> for this processing step.
+     */
+    void setEvioEventLoop(EvioEventLoop loop) {
+        this.loop = loop;
+    }
+    
+    /**
+     * Set the type of event source.
+     * @param sourceType The type of event source.
+     */
+    void setSourceType(SourceType sourceType) {
+        this.sourceType = sourceType;
+    }
+    
+    /**
+     * Load the next <tt>EvioEvent</tt>, either from a record source
+     * or from the <tt>EtEvent</tt> data.
+     */
+    public void processEvent(CompositeRecord record) throws Exception {
+                
+        if (evioEventQueue != null) {
+            EvioEvent evioEvent = null;
+            try {
+                evioEvent = createEvioEvent(record.getEtEvent());                    
+                if (evioEvent == null)
+                    throw new IOException("Failed to create EvioEvent from current EtEvent.");
+                setEventNumber(evioEvent);
+            } catch (EvioException e) {
+                throw new IOException(e);
+            }
+        
+            // Add EvioEvent to the queue for loop.
+            evioEventQueue.addRecord(evioEvent);
+        }
+
+        // Process one EvioEvent.
+        loop.execute(NEXT);         
+        EvioEvent nextEvioEvent = (EvioEvent) loop.getRecordSource().getCurrentRecord();
+        
+        // The call to loop did not create a current record.
+        if (nextEvioEvent == null)
+            throw new NoSuchRecordException("No current EVIO event.");
+        
+        record.setEvioEvent(nextEvioEvent);
+        
+        // Encountered an end of run record.
+        if (EventConstants.isEndEvent(nextEvioEvent))
+            // If stop on end run is enabled, then trigger an exception to end processing.
+            if (stopOnEndRun)
+                throw new EndRunException("EVIO end event received, and stop on end run is enabled.");
+        
+        System.out.println("done with EvioProcessingStep.processEvent");
+    }
+    
+    /**
+     * Create an <tt>EvioEvent</tt> from the current <tt>EtEvent</tt>.
+     * @param etEvent
+     * @return
+     * @throws IOException
+     * @throws EvioException
+     * @throws BufferUnderflowException
+     */
+    private EvioEvent createEvioEvent(EtEvent etEvent) 
+            throws IOException, EvioException, BufferUnderflowException {
+        return (new EvioReader(etEvent.getDataBuffer())).parseNextEvent();
+    }
+    
+    /**
+     * When reading from ET data, the EVIO event number needs to be set manually
+     * from the event ID bank.
+     * @param evioEvent The <tt>EvioEvent</tt> on which to set the event number.
+     */
+    private void setEventNumber(EvioEvent evioEvent) {
+        int eventNumber = -1;
+        if (evioEvent.getChildren() != null) {
+            for (BaseStructure bank : evioEvent.getChildren()) {
+                if (bank.getHeader().getTag() == EventConstants.EVENTID_BANK_TAG) {
+                    eventNumber = bank.getIntData()[0];
+                    break;
+                }
+            }
+        }
+        if (eventNumber != -1)
+            evioEvent.setEventNumber(eventNumber);
+    }
+    
+    /**
+     * Call stop on the EVIO processing loop.
+     */
+    public void endJob() {
+        this.loop.execute(Command.STOP);
+    }
+}
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record
LcioProcessingStep.java added at 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/LcioProcessingStep.java	                        (rev 0)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/LcioProcessingStep.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -0,0 +1,114 @@
+package org.hps.monitoring.record;
+
+import static org.freehep.record.loop.RecordLoop.Command.NEXT;
+
+import org.freehep.record.loop.RecordLoop.Command;
+import org.freehep.record.source.NoSuchRecordException;
+import org.hps.evio.LCSimEventBuilder;
+import org.hps.monitoring.record.composite.CompositeRecord;
+import org.hps.monitoring.record.composite.CompositeRecordProcessor;
+import org.hps.monitoring.record.lcio.LcioEventQueue;
+import org.jlab.coda.jevio.EvioEvent;
+import org.lcsim.event.EventHeader;
+import org.lcsim.util.loop.LCSimLoop;
+
+/**
+ * Processing step for building LCIO events from EVIO
+ * or reading them from an input event file.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+class LcioProcessingStep extends CompositeRecordProcessor {
+
+    LCSimLoop loop = new LCSimLoop();
+    LCSimEventBuilder builder;
+    LcioEventQueue lcioEventQueue;
+    
+    /**
+     * Get the <code>LCSimLoop</code> associated with this processing step.
+     * @return The <code>LCSimLoop</code> associated with this processing step.
+     */
+    LCSimLoop getLoop() {
+        return this.loop;
+    }
+        
+    /**
+     * Set the <code>LCSimEventBuilder</code> for converting from EVIO to LCIO.
+     * @param builder The converter for EVIO to LCIO.
+     */
+    void setEventBuilder(LCSimEventBuilder builder) {
+        this.builder = builder;
+    }
+    
+    /**
+     * Set the <code>LcioEventQueue</code> event source, to be used when there
+     * is no direct LCIO record source from a file.
+     * @param lcioEventQueue The <code>LcioEventQueue</code> to be used as a record source.
+     */
+    void setLcioEventQueue(LcioEventQueue lcioEventQueue) {
+        this.lcioEventQueue = lcioEventQueue;
+        loop.setRecordSource(lcioEventQueue);
+    }
+    
+    /**
+     * Start of job hook.
+     */
+    public void startJob() {
+        if (builder == null)
+            throw new RuntimeException("No LCSimEventBuilder was setup.");
+    }
+    
+    /**
+     * Process a <code>CompositeRecord</code> event by creating an LCIO event
+     * and adding it to the record.
+     */
+    public void processEvent(CompositeRecord record) throws Exception {
+
+        // When the loop does not have a direct LCIO file source, 
+        // the events need to be built from the EVIO input.
+        if (lcioEventQueue != null) {
+            
+            EvioEvent currentEvioEvent = record.getEvioEvent();
+            
+            // Set state on LCIO event builder.
+            builder.readEvioEvent(currentEvioEvent);
+            
+            // The LCIO event will be built if processing an EVIO physics event.
+            if (builder.isPhysicsEvent(currentEvioEvent)) {
+                
+                // Use the event builder to create the next LCIO event.
+                EventHeader lcioEvent = builder.makeLCSimEvent(currentEvioEvent);
+    
+                // Add LCIO event to the queue.
+                lcioEventQueue.addRecord(lcioEvent);
+            } else {
+                // The LCIO processing ignores non-physics events coming from EVIO.
+                return;
+            }
+            
+            if (!loop.getRecordSource().hasNext())
+                throw new NoSuchRecordException("No next LCIO event.");
+        }
+            
+        // Load the next LCIO event.
+        loop.execute(NEXT);
+
+        // The last call to the loop did not create a current record.
+        if (loop.getRecordSource().getCurrentRecord() == null) {
+            throw new NoSuchRecordException("No current LCIO event.");
+        }
+        
+        // Get the current LCIO event.
+        EventHeader lcioEvent = (EventHeader) loop.getRecordSource().getCurrentRecord();
+        
+        // Update the CompositeRecord with reference to the LCIO event.
+        record.setLcioEvent(lcioEvent);
+    }
+    
+    /**
+     * End of job hook.
+     */
+    public void endJob() {
+        // Execute STOP on the LCIO record loop.
+        loop.execute(Command.STOP);
+    }
+}
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite
CompositeRecord.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecord.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecord.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -4,12 +4,16 @@
 import org.jlab.coda.jevio.EvioEvent;
 import org.lcsim.event.EventHeader;
 
+/**
+ * This class is used to group together corresponding ET, EVIO and LCIO events
+ * for use by the {@link CompositeRecordLoop}.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
 public class CompositeRecord {
     
     EtEvent etEvent;
     EvioEvent evioEvent;
     EventHeader lcioEvent;
-    //boolean isValid = true;
     
     public void setEtEvent(EtEvent etEvent) {
         this.etEvent = etEvent;
@@ -34,8 +38,4 @@
     public EventHeader getLcioEvent() {
         return lcioEvent;
     }
-    
-    //public void setInvalid() {
-    //    isValid = false;
-    //}
 }

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite
CompositeRecordLoop.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordLoop.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordLoop.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -1,12 +1,13 @@
 package org.hps.monitoring.record.composite;
 
-import java.util.List;
-
 import org.freehep.record.loop.DefaultRecordLoop;
-import org.freehep.record.loop.RecordLoop;
 import org.freehep.record.source.RecordSource;
-import org.hps.monitoring.record.EventProcessingStep;
 
+/**
+ * Implementation of a composite record loop for processing
+ * ET, EVIO and LCIO events using a single record source.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
 public class CompositeRecordLoop extends DefaultRecordLoop {
 
     CompositeRecordSource recordSource = new CompositeRecordSource();
@@ -18,24 +19,22 @@
         addRecordListener(adapter);
     }
     
+    /**
+     * Set the <code>RecordSource</code> which provides <code>CompositeRecord</code> objects.
+     */
     public void setRecordSource(RecordSource source) {
         if (!source.getRecordClass().isAssignableFrom(CompositeRecord.class)) {
             throw new IllegalArgumentException("The RecordSource has the wrong class.");
         }        
         super.setRecordSource(source);
     }
-        
-    public void addProcessingSteps(List<EventProcessingStep> processingSteps) {
-        recordSource.addProcessingSteps(processingSteps);
-    }
     
-    public void registerRecordLoop(RecordLoop loop) {
-        adapter.registerRecordLoop(loop);
+    /**
+     * Add a <code>CompositeRecordProcessor</code> which will receive <code>CompositeRecord</code>
+     * objects.
+     * @param processor The <code>CompositeRecordProcessor</code> to add.
+     */
+    public void addProcessor(CompositeRecordProcessor processor) {
+        adapter.addProcessor(processor);
     }
-    
-    public void loop(long n) {
-        //super.loop();
-        //execute(Command.GO, true);
-        execute(Command.GO, true);
-    }
 }

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite
CompositeRecordLoopAdapter.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordLoopAdapter.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordLoopAdapter.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -7,42 +7,71 @@
 import org.freehep.record.loop.LoopEvent;
 import org.freehep.record.loop.RecordEvent;
 import org.freehep.record.loop.RecordListener;
-import org.freehep.record.loop.RecordLoop;
-import org.freehep.record.loop.RecordLoop.Command;
 
+/**
+ * Adapter for listening on the {@link CompositeRecordLoop} for records and loop events.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
 public class CompositeRecordLoopAdapter extends AbstractLoopListener implements RecordListener {
 
-    List<RecordLoop> registeredLoops = new ArrayList<RecordLoop>();
-    
+    List<CompositeRecordProcessor> processors = new ArrayList<CompositeRecordProcessor>();
+
+    /**
+     * Callback for loop finish event.
+     * @param loopEvent 
+     */
     public void finish(LoopEvent loopEvent) {
-        System.out.println("CompositeRecordLoopAdapter.finish");
-        for (RecordLoop loop : registeredLoops) {
-            loop.execute(Command.STOP);
-        }
         if (loopEvent.getException() != null)
             loopEvent.getException().printStackTrace();
+      
+        // Call end job hook on all registered processors, which are 
+        // responsible for sending the stop command to their loops, if applicable.
+        for (CompositeRecordProcessor processor : processors) {
+            processor.endJob();
+        }
     }
+
+    /**
+     * Add a <tt>CompositeRecordProcessor</tt> that will listen to this loop.
+     * @param processor The composite record processor to add.
+     */
+    void addProcessor(CompositeRecordProcessor processor) {
+        this.processors.add(processor);
+    }
         
-    void registerRecordLoop(RecordLoop loop) {
-        registeredLoops.add(loop);
-    }
-    
-    /*
-    public void suspend(LoopEvent loopEvent) {
-        for (RecordLoop loop : registeredLoops) {
-            loop.execute(Command.PAUSE);
+    /**
+     * Start event processing which will call {@link CompositeRecordProcessor#startJob()}
+     * on all the registered processors.
+     * @param loopEvent
+     */
+    public void start(LoopEvent loopEvent) {
+        for (CompositeRecordProcessor processor : processors) {
+            processor.startJob();
         }
     }
-    */
     
+    /**
+     * Suspend the loop.
+     * @param loopEvent
+     */
     // NOTE: IOExceptions from loop processing show up here!!!
     public void suspend(LoopEvent loopEvent) {        
-        System.out.println("CompositeRecordLoopAdapter.suspend");
         if (loopEvent.getException() != null)
             loopEvent.getException().printStackTrace();
     }
 
+    /**
+     * Process one record.
+     * @param record 
+     */
     @Override
     public void recordSupplied(RecordEvent record) {
+        for (CompositeRecordProcessor processor : processors) {
+            try {
+                processor.processEvent((CompositeRecord) record.getRecord());
+            } catch (Exception e) {
+                throw new RuntimeException("Error processing CompositeRecord.", e);
+            }
+        }
     }    
-}
+}
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite
CompositeRecordProcessor.java added at 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordProcessor.java	                        (rev 0)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordProcessor.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -0,0 +1,31 @@
+package org.hps.monitoring.record.composite;
+
+import org.hps.monitoring.record.EventProcessor;
+
+/**
+ * An <code>EventProcessor</code> implementation for processing <code>CompositeRecord</code>
+ * records.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public class CompositeRecordProcessor implements EventProcessor<CompositeRecord> {
+
+    @Override
+    public void startJob() {
+    }
+
+    @Override
+    public void startRun(CompositeRecord event) {
+    }
+
+    @Override
+    public void processEvent(CompositeRecord event) throws Exception {
+    }
+
+    @Override
+    public void endRun(CompositeRecord event) {
+    }
+
+    @Override
+    public void endJob() {
+    } 
+}
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite
CompositeRecordSource.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordSource.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordSource.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -1,32 +1,22 @@
 package org.hps.monitoring.record.composite;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
 
 import org.freehep.record.source.AbstractRecordSource;
 import org.freehep.record.source.NoSuchRecordException;
-import org.hps.monitoring.record.EventProcessingStep;
 
-
+/**
+ * A record source providing <code>CompositeRecord</code> objects.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
 public class CompositeRecordSource extends AbstractRecordSource {
 
     CompositeRecord currentRecord;
-    List<EventProcessingStep> processingSteps = new ArrayList<EventProcessingStep>();
             
     public void next() throws IOException, NoSuchRecordException {
         currentRecord = new CompositeRecord();
-        
-        // Execute sub-processing that will alter the CompositeRecord.
-        for (EventProcessingStep step : this.processingSteps) {
-            step.execute();
-        }
     }
-        
-    void addProcessingSteps(List<EventProcessingStep> processingSteps) {
-        this.processingSteps = processingSteps;
-    }    
-    
+            
     @Override
     public Object getCurrentRecord() throws IOException {
         return currentRecord;

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/etevent
EtEventListener.java removed after 729
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/etevent/EtEventListener.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/etevent/EtEventListener.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -1,51 +0,0 @@
-package org.hps.monitoring.record.etevent;
-
-/**
- * Interface for notifying listeners of ET ring events.
- * @author Jeremy McCormick <[log in to unmask]>
- * @version $Id: EtEventListener.java,v 1.1 2012/05/03 16:59:28 jeremy Exp $
- */
-// FIXME: Should all the callback methods get an EtEvent or event number?
-public interface EtEventListener {
-
-    /**
-     * Called at beginning of event processing session.
-     */
-    void begin();
-
-    /**
-     * Called at start of single EtEvent.
-     */
-    void startOfEvent();
-    
-    /**
-     * Called at end of processing single EtEvent.
-     */
-    void endOfEvent();
-
-    /**
-     * Called when an error occurs processing current EtEvent.
-     */
-    void errorOnEvent();
-
-    /**
-     * Called when event processing session finishes.
-     */
-    void finish();
-    
-    /** 
-     * Called when a Pre Start event is received from the ET ring,
-     * indicating start of run.
-     * @param seconds Unix time in seconds.
-     * @param runNumber The run number.
-     */
-    void prestart(int seconds, int runNumber);
-    
-    /**
-     * Called when an End Event is received from the ET ring,
-     * indicating end of run.
-     * @param seconds Unix time in seconds.
-     * @param nevents Number of events in run.
-     */
-    void endRun(int seconds, int nevents);
-}
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/etevent
EtEventLoop.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/etevent/EtEventLoop.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/etevent/EtEventLoop.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -19,28 +19,23 @@
         addLoopListener(adapter);
         addRecordListener(adapter);
     }
-    
+ 
+    /**
+     * Add an <code>EtEventProcessor</code> to the loop.
+     * @param processor The <code>EtEventProcessor</code> to add.
+     */
     public void addEtEventProcessor(EtEventProcessor processor) {
         adapter.addEtEventProcessor(processor);
     }
     
+    /**
+     * Set the <code>RecordSource</code> for the loop.
+     * @param source The <code>RecordSource</code> for the loop.
+     */
     public void setRecordSource(RecordSource source) {
         if (!source.getRecordClass().isAssignableFrom(EtEvent.class)) {
             throw new IllegalArgumentException("The RecordSource has the wrong class.");
         }        
         super.setRecordSource(source);
-    }           
-    
-    public long loop(long number) throws IOException {
-        if (number < 0L) {
-            execute(Command.GO, true);
-        } else {
-            execute(Command.GO_N, number, true);
-            execute(Command.STOP);
-        }
-        Throwable t = getProgress().getException();
-        if (t != null && t instanceof IOException)
-            throw (IOException) t;
-        return getSupplied();
     }
 }

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/evio
EvioAdapter.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/evio/EvioAdapter.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/evio/EvioAdapter.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -45,7 +45,9 @@
     
     @Override
     public void finish(LoopEvent event) {
+        System.out.println("EvioAdapter.finish");
         for (EvioEventProcessor processor : processors) {
+            System.out.println(processor.getClass().getCanonicalName() + ".endJob");
             processor.endJob();
         }
     }    

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/evio
EvioEventLoop.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/evio/EvioEventLoop.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/evio/EvioEventLoop.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -3,7 +3,6 @@
 import java.io.IOException;
 
 import org.freehep.record.loop.DefaultRecordLoop;
-import org.freehep.record.loop.RecordLoop.Command;
 import org.freehep.record.source.RecordSource;
 import org.jlab.coda.jevio.EvioEvent;
 

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/evio
EvioEventProcessor.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/evio/EvioEventProcessor.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/evio/EvioEventProcessor.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -12,7 +12,7 @@
 public abstract class EvioEventProcessor implements EventProcessor<EvioEvent> {
     
     @Override
-    public void startJob() {        
+    public void startJob() {
     }
     
     @Override

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys
SystemStatus.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/SystemStatus.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/SystemStatus.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -18,6 +18,7 @@
      */
     enum StatusCode {
         
+        // Status encodings with a string name and descriptor.
         OKAY   (0, "okay",    "The system appears to be working."),
         UNKNOWN(1, "unknown", "The status is not known."),
         OFFLINE(2, "offline", "The system is currently offline."),               
@@ -36,14 +37,26 @@
             this.description = description;
         }
         
+        /**
+         * Get the raw int code for the status.
+         * @return The raw code.
+         */
         int getRawCode() {
             return code;
         }
         
+        /**
+         * Get the name of the status.
+         * @return The name of the status.
+         */
         String getName() {
             return name;
         }                  
         
+        /**
+         * Get the description of the status.
+         * @return The description of the status.
+         */
         String getDescription() {
             return description;
         }

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys
SystemStatusImpl.java 729 -> 730
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/SystemStatusImpl.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/SystemStatusImpl.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -59,7 +59,10 @@
     public long getLastChangedMillis() {
         return lastChangedMillis;
     }
-        
+
+    /**
+     * Notify listeners of changes to the system status.
+     */
     void notifyListeners() {
         for (SystemStatusListener listener : listeners) {
             listener.statusChanged(this);

java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record
EventProcessingChainTest.java 729 -> 730
--- java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record/EventProcessingChainTest.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record/EventProcessingChainTest.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -43,8 +43,7 @@
         processing.setDetectorName(detectorName);
         processing.add(new DummyEvioProcessor());
         processing.add(new DummyDriver());
-        processing.setStopOnEndRun();
-        processing.configure();
+        processing.setup();
         processing.loop();
     }
     

java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record
EvioEventProcessingTest.java 729 -> 730
--- java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record/EvioEventProcessingTest.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record/EvioEventProcessingTest.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -24,8 +24,7 @@
         processing.setDetectorName(detectorName);
         processing.add(new DummyEvioProcessor());
         processing.add(new DummyDriver());
-        processing.setStopOnEndRun();
-        processing.configure();
+        processing.setup();
         processing.loop();
         processing.finish();
     }

java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record/etevent
EtEventLoopTest.java 729 -> 730
--- java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record/etevent/EtEventLoopTest.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record/etevent/EtEventLoopTest.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -2,6 +2,7 @@
 
 import java.io.IOException;
 
+import org.freehep.record.loop.RecordLoop.Command;
 import org.jlab.coda.et.EtEvent;
 import org.jlab.coda.et.EtEventImpl;
 
@@ -24,11 +25,7 @@
             queue.addRecord(event);
         }
         
-        try {
-            loop.loop(-1);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
+        loop.execute(Command.GO, true);
         
         System.out.println("loop processed " + loop.getTotalSupplied() + " records");
     }

java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record/etevent
MultiThreadedEtEventLoopTest.java 729 -> 730
--- java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record/etevent/MultiThreadedEtEventLoopTest.java	2014-06-20 15:10:45 UTC (rev 729)
+++ java/trunk/monitoring-app/src/test/java/org/hps/monitoring/record/etevent/MultiThreadedEtEventLoopTest.java	2014-06-20 19:01:19 UTC (rev 730)
@@ -1,7 +1,6 @@
 package org.hps.monitoring.record.etevent;
 
-import java.io.IOException;
-
+import org.freehep.record.loop.RecordLoop.Command;
 import org.jlab.coda.et.EtEvent;
 import org.jlab.coda.et.EtEventImpl;
 
@@ -63,11 +62,7 @@
         }
 
         public void run() {
-            try {
-                loop.loop(-1);
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
+            loop.execute(Command.GO, false);
         }
     }
 
SVNspam 0.1