Author: [log in to unmask] Date: Mon Apr 13 17:23:55 2015 New Revision: 2681 Log: Code cleanup to record-util module. Added: java/trunk/record-util/src/main/java/org/hps/job/package-info.java java/trunk/record-util/src/main/java/org/hps/record/composite/package-info.java java/trunk/record-util/src/main/java/org/hps/record/enums/package-info.java java/trunk/record-util/src/main/java/org/hps/record/epics/package-info.java java/trunk/record-util/src/main/java/org/hps/record/et/package-info.java java/trunk/record-util/src/main/java/org/hps/record/evio/package-info.java java/trunk/record-util/src/main/java/org/hps/record/lcio/package-info.java java/trunk/record-util/src/main/java/org/hps/record/scalars/package-info.java Modified: java/trunk/record-util/src/main/java/org/hps/job/JobManager.java java/trunk/record-util/src/main/java/org/hps/record/AbstractRecordProcessor.java java/trunk/record-util/src/main/java/org/hps/record/AbstractRecordQueue.java java/trunk/record-util/src/main/java/org/hps/record/EndRunException.java java/trunk/record-util/src/main/java/org/hps/record/LCSimEventBuilder.java java/trunk/record-util/src/main/java/org/hps/record/MaxRecordsException.java java/trunk/record-util/src/main/java/org/hps/record/RecordProcessingException.java java/trunk/record-util/src/main/java/org/hps/record/RecordProcessor.java java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoop.java java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoopAdapter.java java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoopConfiguration.java java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecord.java java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecordProcessor.java java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecordSource.java java/trunk/record-util/src/main/java/org/hps/record/composite/EtEventAdapter.java java/trunk/record-util/src/main/java/org/hps/record/composite/EventProcessingThread.java java/trunk/record-util/src/main/java/org/hps/record/composite/EvioEventAdapter.java java/trunk/record-util/src/main/java/org/hps/record/composite/LcioEventAdapter.java java/trunk/record-util/src/main/java/org/hps/record/composite/LcioEventSupplier.java java/trunk/record-util/src/main/java/org/hps/record/composite/MaxRecordsProcessor.java java/trunk/record-util/src/main/java/org/hps/record/composite/RecordProcessorAdapter.java java/trunk/record-util/src/main/java/org/hps/record/enums/DataSourceType.java java/trunk/record-util/src/main/java/org/hps/record/enums/ProcessingStage.java java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEtProcessor.java java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEvioProcessor.java java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsGenericObject.java java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsScalarData.java java/trunk/record-util/src/main/java/org/hps/record/et/EtConnection.java java/trunk/record-util/src/main/java/org/hps/record/et/EtEventProcessor.java java/trunk/record-util/src/main/java/org/hps/record/et/EtEventQueue.java java/trunk/record-util/src/main/java/org/hps/record/et/EtEventSource.java java/trunk/record-util/src/main/java/org/hps/record/et/EtStationThread.java java/trunk/record-util/src/main/java/org/hps/record/et/PreStartProcessor.java java/trunk/record-util/src/main/java/org/hps/record/evio/EvioDetectorConditionsProcessor.java java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventConstants.java java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventProcessor.java java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventQueue.java java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventUtilities.java java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileProducer.java java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileSource.java java/trunk/record-util/src/main/java/org/hps/record/lcio/LcioEventQueue.java java/trunk/record-util/src/main/java/org/hps/record/package-info.java java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarData.java java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarUtilities.java java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarsEvioProcessor.java java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarsGenericObject.java Modified: java/trunk/record-util/src/main/java/org/hps/job/JobManager.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/job/JobManager.java (original) +++ java/trunk/record-util/src/main/java/org/hps/job/JobManager.java Mon Apr 13 17:23:55 2015 @@ -6,52 +6,59 @@ import org.lcsim.util.Driver; /** - * Extension of standard LCSim job manager which does some HPS-specific management - * of the conditions system. - * - * @author Jeremy McCormick <[log in to unmask]> + * Extension of standard LCSim job manager which does some HPS-specific management of the conditions system. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public class JobManager extends JobControlManager { - + + /** + * Run the job manager from the command line. + * + * @param args the command line arguments + */ + public static void main(final String args[]) { + // Run the job. + final JobManager job = new JobManager(); + job.run(args); + } + + /** + * Class constructor. + */ public JobManager() { // Always want to reset conditions system before starting the job. DatabaseConditionsManager.resetInstance(); } - - public static void main(String args[]) { - // Run the job. - JobManager job = new JobManager(); - job.run(args); - } - + /** - * Override the parent classes method that runs the job in order to do - * conditions system initialization, if required. - * @return True if job was successful. + * Override the parent classes method that runs the job in order to perform conditions system initialization. + * + * @return <code>true</code> if job was successful */ @Override - public boolean run() { - + public final boolean run() { + // Setup the conditions if there is a ConditionsDriver present. setupConditions(); - + // Run the job. - boolean result = super.run(); - - // Close the conditions database connection if it is open. + final boolean result = super.run(); + + // Close the conditions database connection if it is open. DatabaseConditionsManager.getInstance().closeConnection(); - + return result; } /** - * This method will find the {@link org.hps.conditions.ConditionsDriver} in the - * list of Drivers registered with the manager and execute its initialization - * method, which can override the default behavior of the conditions system. + * This method will find the {@link org.hps.conditions.ConditionsDriver} in the list of Drivers registered with the + * manager and then execute its initialization method, which may override the default behavior of the conditions + * system. */ private void setupConditions() { ConditionsDriver conditionsDriver = null; - for (Driver driver : this.getDriverAdapter().getDriver().drivers()) { + for (final Driver driver : this.getDriverAdapter().getDriver().drivers()) { if (driver instanceof ConditionsDriver) { conditionsDriver = (ConditionsDriver) driver; break; Added: java/trunk/record-util/src/main/java/org/hps/job/package-info.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/job/package-info.java (added) +++ java/trunk/record-util/src/main/java/org/hps/job/package-info.java Mon Apr 13 17:23:55 2015 @@ -0,0 +1,6 @@ +/** + * This package currently contains only a simple extension to the LCSim {@link org.lcsim.job.JobControlManager} class. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ +package org.hps.job; Modified: java/trunk/record-util/src/main/java/org/hps/record/AbstractRecordProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/AbstractRecordProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/AbstractRecordProcessor.java Mon Apr 13 17:23:55 2015 @@ -1,35 +1,62 @@ package org.hps.record; - /** - * An abstract implementation of {@link RecordProcessor} with "no op" method implementions. + * An abstract implementation of {@link RecordProcessor} with "no operation" method implementations. + * <p> * Concrete implementations of <code>RecordProcessor</code> should extend this class. * - * @param <RecordType> The type of the record processed by this class. + * @param <RecordType> the type of the record processed by this class + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public abstract class AbstractRecordProcessor<RecordType> implements RecordProcessor<RecordType> { + /** + * End of job action. + */ @Override - public void startJob() { + public void endJob() { } + /** + * End of run action. + * + * @param record the current record being processed + */ @Override - public void startRun(RecordType record) { + public void endRun(final RecordType record) { } + /** + * Process a record. + * + * @param record the record to process + * @throws Exception never but sub-classes may throw + */ @Override - public void process(RecordType record) throws Exception { + public void process(final RecordType record) throws Exception { } + /** + * Start of job action. + */ @Override - public void endRun(RecordType record) { + public void startJob() { } + /** + * Start of run action. + * + * @param record the current record being processed (usually some kind of start-of-run record such as an EVIO + * PRESTART record) + */ @Override - public void endJob() { + public void startRun(final RecordType record) { } + /** + * Suspend event processing (usually this will not be implemented by a sub-class). + */ @Override - public void suspend() { + public void suspend() { } } Modified: java/trunk/record-util/src/main/java/org/hps/record/AbstractRecordQueue.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/AbstractRecordQueue.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/AbstractRecordQueue.java Mon Apr 13 17:23:55 2015 @@ -9,93 +9,144 @@ import org.freehep.record.source.NoSuchRecordException; /** - * Implementation of <tt>AbstractRecordSource</tt> using a dynamic queue that - * can receive events "on the fly" e.g. from an ET ring. Polling is used in the - * {@link #next()} method to get the next record, which might not be immediately - * available. + * Implementation of <tt>AbstractRecordSource</tt> using a dynamic queue that can receive events "on the fly", e.g. from + * an ET ring. + * <p> + * Polling is used in the {@link #next()} method to get the next record, which might not be immediately available. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public abstract class AbstractRecordQueue<RecordType> extends AbstractRecordSource { - // The queue, which is a linked list with blocking behavior. - BlockingQueue<RecordType> records; - - // The current LCIO events. - RecordType currentRecord; - - // The amount of time to wait for an LCIO event from the queue before dying. + /** + * The current record. + */ + private RecordType currentRecord; + + /** + * The record queue which is a linked list with blocking behavior. + */ + private final BlockingQueue<RecordType> records; + + /** + * The amount of time to wait for a record to be available in the queue. The default value of -1 will essentially + * use a zero wait time. + */ long timeOutMillis = -1; - - + /** - * Constructor that takes the timeout time in seconds. - * @param timeoutSeconds the timeout time in seconds + * Class constructor. */ - public AbstractRecordQueue(long timeoutMillis, int maxSize) { - this.timeOutMillis = timeoutMillis; - records = new LinkedBlockingQueue<RecordType>(maxSize); + public AbstractRecordQueue() { + // Use an unlimited queue size by default. + this.records = new LinkedBlockingQueue<RecordType>(); } - - public AbstractRecordQueue() { - // Unlimited queue size. - records = new LinkedBlockingQueue<RecordType>(); + + /** + * Class constructor with the timeout in seconds. + * + * @param timeoutSeconds the timeout in seconds + */ + public AbstractRecordQueue(final long timeOutMillis, final int maxSize) { + this.timeOutMillis = timeOutMillis; + this.records = new LinkedBlockingQueue<RecordType>(maxSize); } - + /** - * Add a record to the queue. - * If the queue is full, then drain it first. + * Add a record to the queue if there is space. + * * @param event the LCIO event to add */ - public void addRecord(RecordType record) { - if (records.remainingCapacity() > 0) - records.add(record); - // TODO: Maybe automatically drain the queue here if at capacity??? + // FIXME: Should drain queue if over capacity. + public void addRecord(final RecordType record) { + if (this.records.remainingCapacity() > 0) { + this.records.add(record); + } } - + + /** + * Get the current record. + * + * @return the current record + * @throws IOException never + */ @Override public Object getCurrentRecord() throws IOException { - return currentRecord; + return this.currentRecord; } - + + /** + * Return <code>true</code> if there is a current record. + * + * @return <code>true</code> if there is a current record + */ + @Override + public boolean hasCurrent() { + return this.currentRecord != null; + } + + /** + * Return <code>true</code> if there is a next record (e.g. queue is not empty). + * + * @return <code>true</code> if there is a next record + */ + @Override + public boolean hasNext() { + return this.records.size() != 0; + } + + /** + * Load the next record. + * + * @throws IOException never + * @throws NoSuchRecordException if there are no records available from the queue + */ + @Override + public void next() throws IOException, NoSuchRecordException { + try { + if (this.timeOutMillis > 0L) { + // Poll the queue for the next record until timeout is exceeded. + this.currentRecord = this.records.poll(this.timeOutMillis, TimeUnit.MILLISECONDS); + } else { + // Poll without an explicit wait time which will immediately return + // null if the queue is empty. + this.currentRecord = this.records.poll(); + } + } catch (final InterruptedException e) { + e.printStackTrace(); + } + if (this.currentRecord == null) { + throw new NoSuchRecordException("No records in queue."); + } + } + + /** + * Get the number of records in the queue. + * + * @return the number of records in the queue + */ + @Override + public long size() { + return this.records.size(); + } + + /** + * Returns <code>true</code> to indicate current record capability is supported. + * + * @return <code>true</code> because current record capability is supported + */ @Override public boolean supportsCurrent() { return true; } + /** + * Returns <code>true</code> to indicate next record capability is supported. + * + * @return <code>true</code> because next record capability is supported + */ @Override public boolean supportsNext() { return true; } - - @Override - public boolean hasCurrent() { - return currentRecord != null; - } - - @Override - public boolean hasNext() { - return records.size() != 0; - } - - @Override - public void next() throws IOException, NoSuchRecordException { - try { - if (timeOutMillis > 0L) - // Poll the queue for the next record or until timeout is exceeded. - currentRecord = records.poll(timeOutMillis, TimeUnit.MILLISECONDS); - else - // Poll without an explicit wait time which will immediately return - // null if queue is empty. - currentRecord = records.poll(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (currentRecord == null) { - throw new NoSuchRecordException("No records in queue."); - } - } - - @Override - public long size() { - return records.size(); - } } Modified: java/trunk/record-util/src/main/java/org/hps/record/EndRunException.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/EndRunException.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/EndRunException.java Mon Apr 13 17:23:55 2015 @@ -1,23 +1,36 @@ package org.hps.record; /** - * An Exception thrown when an end run occurs. + * An <code>Exception</code> thrown when end of run occurs in event processing. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ -public class EndRunException extends RuntimeException { - - int runNumber; - - public EndRunException(String message, int runNumber) { +@SuppressWarnings("serial") +public final class EndRunException extends RuntimeException { + + /** + * The run number. + */ + private final int runNumber; + + /** + * Class constructor. + * + * @param message the message + * @param runNumber the run number + */ + public EndRunException(final String message, final int runNumber) { super(message); this.runNumber = runNumber; } - + /** * Get the run number. + * * @return The run number. */ public int getRunNumber() { - return runNumber; + return this.runNumber; } - + } Modified: java/trunk/record-util/src/main/java/org/hps/record/LCSimEventBuilder.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/LCSimEventBuilder.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/LCSimEventBuilder.java Mon Apr 13 17:23:55 2015 @@ -5,24 +5,26 @@ import org.lcsim.event.EventHeader; /** - * This is an interface that should be implemented by classes that - * build LCSim events from EVIO raw data. - * @author Jeremy McCormick <[log in to unmask]> + * This is an interface that should be implemented by classes which build LCSim events from EVIO raw data. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public interface LCSimEventBuilder extends ConditionsListener { /** - * Read information from an EVIO control event such as go or pre start - * to set the event builder's state. This does not actually build an - * LCSim event. - * @param evioEvent The input EvioEvent. + * Build the LCSim event from an EVIO event. + * + * @param evioEvent the input <code>EvioEvent</code> + * @return the LCSim event + */ + EventHeader makeLCSimEvent(EvioEvent evioEvent); + + /** + * Read information from an EVIO control event such as a PRESTART event to set the event builder's state. + * <p> + * This does not actually build an LCSim event. + * + * @param evioEvent the input <code>EvioEvent</code> */ void readEvioEvent(EvioEvent evioEvent); - - /** - * Build the LCSim event from EVIO data. - * @param evioEvent The input EvioEvent. - * @return The LCSim event. - */ - EventHeader makeLCSimEvent(EvioEvent evioEvent); } Modified: java/trunk/record-util/src/main/java/org/hps/record/MaxRecordsException.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/MaxRecordsException.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/MaxRecordsException.java Mon Apr 13 17:23:55 2015 @@ -2,22 +2,35 @@ /** * Exception thrown when maximum number of records is reached. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ -// FIXME: Use loop(nevents) instead of this for controlling number of records run. -public class MaxRecordsException extends RuntimeException { +// FIXME: Use loop methods instead of this for controlling number of records run. +@SuppressWarnings("serial") +public final class MaxRecordsException extends RuntimeException { - long maxRecords; - - public MaxRecordsException(String message, long maxRecords) { + /** + * The maximum number of records. + */ + private final long maxRecords; + + /** + * Class constructor. + * + * @param message the message + * @param maxRecords the maximum number of records + */ + public MaxRecordsException(final String message, final long maxRecords) { super(message); this.maxRecords = maxRecords; } - + /** * Get the maximum number of records. - * @return The maximum number of records. + * + * @return the maximum number of records */ public long getMaxRecords() { - return maxRecords; + return this.maxRecords; } } Modified: java/trunk/record-util/src/main/java/org/hps/record/RecordProcessingException.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/RecordProcessingException.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/RecordProcessingException.java Mon Apr 13 17:23:55 2015 @@ -1,18 +1,31 @@ package org.hps.record; /** - * Generic error type for exceptions that occur during event processing. - * It extends <code>RuntimeException</code> so that methods need not - * declare a <code>throws</code> clause in their definitions to use it. + * This is a generic error type for exceptions that occur during event processing. It extends + * <code>RuntimeException</code> so that methods need not declare a <code>throws</code> clause in order to use it. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ -public class RecordProcessingException extends RuntimeException { - - public RecordProcessingException(String message, Throwable x) { +@SuppressWarnings("serial") +public class RecordProcessingException extends RuntimeException { + + /** + * Class constructor. + * + * @param message the error message + */ + public RecordProcessingException(final String message) { + super(message); + } + + /** + * Class constructor. + * + * @param message the error message + * @param x cause of the error + */ + public RecordProcessingException(final String message, final Throwable x) { super(message, x); } - - public RecordProcessingException(String message) { - super(message); - } - + } Modified: java/trunk/record-util/src/main/java/org/hps/record/RecordProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/RecordProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/RecordProcessor.java Mon Apr 13 17:23:55 2015 @@ -1,46 +1,48 @@ package org.hps.record; /** - * This is a generic interface for event processing which implements - * hooks for starting the job, starting a new run, processing individual - * records, ending a run and ending a job. This interface should not - * be implemented directly. Instead the {@link AbstractRecordProcessor} - * should be extended with a specific type declaration. + * This is a generic interface for event processing which implements hooks for starting the job, starting a new run, + * processing individual records, ending a run and ending a job. This interface should not be implemented directly. + * Instead the {@link AbstractRecordProcessor} should be extended with a specific type declaration. * - * @param <RecordType> The concrete type of the event record. + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + * @param <RecordType> the concrete type of the event record */ public interface RecordProcessor<RecordType> { - + + /** + * End of job action. + */ + void endJob(); + + /** + * End of run action. + * + * @param record the record to process + */ + void endRun(RecordType record); + + /** + * Process a single event. + * + * @param record the record to process + */ + void process(RecordType record) throws Exception; + /** * Start of job action. */ void startJob(); - + /** * Start run action. - * @param record + * + * @param record the record to process */ void startRun(RecordType record); - - /** - * Process a single event. - * @param record - */ - void process(RecordType record) throws Exception; /** - * End of run action. - * @param record - */ - void endRun(RecordType record); - - /** - * End of job action. - */ - void endJob(); - - /** - * Action to be taken when recording processing is suspended. + * Suspend processing action. */ void suspend(); } Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoop.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoop.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoop.java Mon Apr 13 17:23:55 2015 @@ -28,334 +28,367 @@ import org.lcsim.util.loop.LCIOEventSource; /** - * Implementation of a composite record loop for processing - * ET, EVIO and LCIO events using a single record source. + * Implementation of a composite record loop for processing ET, EVIO and LCIO events using a single record source. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public final class CompositeLoop extends DefaultRecordLoop { - CompositeRecordSource recordSource = new CompositeRecordSource(); - List<CompositeLoopAdapter> adapters = new ArrayList<CompositeLoopAdapter>(); - - boolean paused = false; - boolean stopOnErrors = true; - - CompositeLoopConfiguration config = null; - - /** - * No argument constructor. - * The {@link #setCompositeLoopConfiguration(CompositeLoopConfiguration)} method must be - * called on the loop manually. + /** + * Return <code>true</code> if the Throwable is a type that can be thrown by the ET system when it is attempting to + * read events from the server. + * <p> + * The <code>IOException</code> type is not included here but can actually be thrown by the ET system + * + * @param e the Exception + * @return <code>true</code> if the object can be thrown by ET event reading + */ + private static boolean isEtReadException(final Throwable e) { + return e instanceof EtException || e instanceof EtDeadException || e instanceof EtClosedException + || e instanceof EtEmptyException || e instanceof EtBusyException || e instanceof EtTimeoutException + || e instanceof EtWakeUpException; + } + + /** + * The list of record adapters that are activated for every record being processed. + */ + private final List<CompositeLoopAdapter> adapters = new ArrayList<CompositeLoopAdapter>(); + + /** + * The composite loop configuration. + */ + private CompositeLoopConfiguration config = null; + + /** + * Paused flag. + */ + private boolean paused = false; + + /** + * The record source. + */ + private final CompositeRecordSource recordSource = new CompositeRecordSource(); + + /** + * Flag to stop on event processing errors. + */ + private boolean stopOnErrors = true; + + /** + * Class constructor. + * <p> + * The {@link #setCompositeLoopConfiguration(CompositeLoopConfiguration)} method must be called on the loop manually + * to configure it for processing. */ public CompositeLoop() { - setRecordSource(recordSource); - } - + setRecordSource(this.recordSource); + } + /** * Create the loop with the given configuration. - * @param config The configuration parameters of the loop. - */ - public CompositeLoop(CompositeLoopConfiguration config) { - setRecordSource(recordSource); + * + * @param config the configuration parameters of the loop + */ + public CompositeLoop(final CompositeLoopConfiguration config) { + setRecordSource(this.recordSource); setCompositeLoopConfiguration(config); } - - /** - * Set to true in order to have this loop stop on all - * event processing errors. Certain types of fatal errors - * will never be ignored. - * @param stopOnErrors True for this loop to stop on errors. - */ - public void setStopOnErrors(boolean stopOnErrors) { - this.stopOnErrors = stopOnErrors; - } - - /** - * Add a {@link CompositeLoopAdapter} which will process - * {@link CompositeRecord} objects. - * @param adapter The CompositeLoopAdapter object. - */ - public void addAdapter(CompositeLoopAdapter adapter) { + + /** + * Add a {@link CompositeLoopAdapter} which will process {@link CompositeRecord} objects. + * + * @param adapter the CompositeLoopAdapter object + */ + public void addAdapter(final CompositeLoopAdapter adapter) { addLoopListener(adapter); - addRecordListener(adapter); - adapters.add(adapter); - } - - /** - * Set the <code>RecordSource</code> which provides <code>CompositeRecord</code> objects. - */ - public final void setRecordSource(RecordSource source) { - if (!source.getRecordClass().isAssignableFrom(CompositeRecord.class)) { - throw new IllegalArgumentException("The RecordSource has the wrong class."); - } - super.setRecordSource(source); - } - - /** - * Handle errors from the client such as registered adapters. - * If the loop is setup to try and continue on errors, - * only non-fatal record processing exceptions are ignored. - */ - protected void handleClientError(Throwable x) { - + addRecordListener(adapter); + this.adapters.add(adapter); + } + + /** + * Get the last error that occurred. + * + * @return the last error that occurred + */ + public Throwable getLastError() { + return this._exception; + } + + /** + * Handle errors from the client including any registered adapters. + * <p> + * If the loop is setup to try and continue on errors, only non-fatal record processing exceptions are ignored. + * + * @param x the error that occurred + */ + @Override + protected void handleClientError(final Throwable x) { + x.printStackTrace(); - + // Is the error ignorable? if (isIgnorable(x)) { // Ignore the error! return; } - + // Set the exception on the super class. this._exception = x; - + // Stop the event processing. this.execute(Command.STOP); } /** * Handle errors thrown by the <code>RecordSource</code>. - */ - protected void handleSourceError(Throwable x) { + * + * @param x the error that occurred + */ + @Override + protected void handleSourceError(final Throwable x) { x.printStackTrace(); - + // Is the error ignorable? if (isIgnorable(x)) { // Ignore the error! return; } - + // Set the exception on the super class. this._exception = x; - + // Stop the event processing. this.execute(Command.STOP); - } - - /** - * <p> - * True if an error is ignore-able. If <code>stopOnErrors</code> - * is true, then this method always returns false. Otherwise, - * the error cause determines whether the loop can continue - * processing. - * <p> - * The assumption here is that errors coming from event processing - * of the composite records are caught in the adapters and then wrapped - * in a {@link org.hps.record.RecordProcessingException}. Certain - * errors which should never be ignored are also wrapped in a - * similar way, so we need to check for these error types before - * assuming that event processing can continue. - * - * @param x The error that occurred. - * @return True if the error can be ignored. - */ - private boolean isIgnorable(Throwable x) { - if (!stopOnErrors) { + } + + /** + * <p> + * Return <code>true</code> if an error is ignore-able. + * <p> + * If <code>stopOnErrors</code> is true, then this method always returns <code>false</code>. Otherwise, the error's + * cause determines whether the loop can continue processing. + * <p> + * The assumption here is that errors coming from event processing of the composite records are caught in the + * adapters and then wrapped in a {@link org.hps.record.RecordProcessingException}. Certain errors which should + * never be ignored are also wrapped in a similar way, so we need to check for these error types before assuming + * that event processing can continue. + * + * @param x the error that occurred + * @return <code>true</code> if the error is ignorable + */ + private boolean isIgnorable(final Throwable x) { + if (!this.stopOnErrors) { if (x instanceof RecordProcessingException) { - Throwable cause = x.getCause(); - if (cause instanceof MaxRecordsException || - cause instanceof EndRunException || - cause instanceof NoSuchRecordException || - isEtReadException(cause)) { - // These types of exceptions are never ignored. - return false; - } else { - // Other types of record processing exceptions are considered non-fatal. - return true; - } - } - } - return false; - } - - /** - * True if the Throwable is a type that can be thrown by the ET - * system when it is attempting to read events from the server. - * The <code>IOException</code> type is ignored but can actually - * be thrown. - * @param e The Exception. - * @return True if the object can be thrown by ET event reading. - */ - private static boolean isEtReadException(Throwable e) { - return e instanceof EtException || e instanceof EtDeadException - || e instanceof EtClosedException || e instanceof EtEmptyException - || e instanceof EtBusyException || e instanceof EtTimeoutException - || e instanceof EtWakeUpException; - } - - /** - * Get the last error that occurred. - * @return The last error that occurred. - */ - public Throwable getLastError() { - return _exception; - } - - /** - * Pause the event processing. - */ - public void pause() { - execute(Command.PAUSE); - paused = true; - } - - /** - * Resume event processing from pause mode. - */ - public void resume() { - paused = false; - } - - /** - * True if loop is paused. - * @return True if loop is current paused. + final Throwable cause = x.getCause(); + return !(cause instanceof MaxRecordsException || cause instanceof EndRunException + || cause instanceof NoSuchRecordException || isEtReadException(cause)); + } + } + return false; + } + + /** + * Return <code>true</code> if the loop is paused. + * + * @return <code>true</code> if loop is paused */ public boolean isPaused() { - return paused; - } - + return this.paused; + } + /** * Loop over events from the source. - * @param number The number of events to process or -1 for unlimited. - * @return The number of records that were processed. - */ - public long loop(long number) { + * + * @param number the number of events to process or -1L to process until record source is exhausted + * @return the number of records that were processed + */ + public long loop(final long number) { if (number < 0L) { execute(Command.GO, true); } else { execute(Command.GO_N, number, true); - execute(Command.STOP); + execute(Command.STOP); } return getSupplied(); } - - public void setConfiguration(Object object) { - if (object instanceof CompositeLoopConfiguration) { - setCompositeLoopConfiguration((CompositeLoopConfiguration)object); - } else { - throw new IllegalArgumentException("Wrong type of object to configure CompositeLoop: " + object.getClass().getCanonicalName()); - } - } - + + /** + * Pause the event processing. + */ + public void pause() { + execute(Command.PAUSE); + this.paused = true; + } + + /** + * Resume event processing from pause mode. + */ + public void resume() { + this.paused = false; + } + /** * Configure the loop using a {@link CompositeLoopConfiguration} object. - * @param config The CompositeLoopConfiguration object containing the loop configuration parameter values. - */ - void setCompositeLoopConfiguration(CompositeLoopConfiguration config) { - + * + * @param config the <code>CompositeLoopConfiguration</code> object containing the loop configuration + */ + private void setCompositeLoopConfiguration(final CompositeLoopConfiguration config) { + if (this.config != null) { throw new RuntimeException("CompositeLoop has already been configured."); } - + this.config = config; - + EtEventAdapter etAdapter = null; EvioEventAdapter evioAdapter = null; LcioEventAdapter lcioAdapter = null; - CompositeLoopAdapter compositeAdapter = new CompositeLoopAdapter(); - + final CompositeLoopAdapter compositeAdapter = new CompositeLoopAdapter(); + // Was there no RecordSource provided explicitly? - if (config.recordSource == null) { + if (config.getRecordSource() == null) { // Using an ET server connection? - if (config.sourceType.equals(DataSourceType.ET_SERVER)) { - if (config.connection != null) - etAdapter = new EtEventAdapter(new EtEventSource(config.connection)); - else + if (config.getDataSourceType().equals(DataSourceType.ET_SERVER)) { + if (config.getEtConnection() != null) { + etAdapter = new EtEventAdapter(new EtEventSource(config.getEtConnection())); + } else { throw new IllegalArgumentException("Configuration is missing a valid ET connection."); - // Using an EVIO file? - } else if (config.sourceType.equals(DataSourceType.EVIO_FILE)) { - if (config.filePath != null) { - evioAdapter = new EvioEventAdapter(new EvioFileSource(new File(config.filePath))); + // Using an EVIO file? + } + } else if (config.getDataSourceType().equals(DataSourceType.EVIO_FILE)) { + if (config.getFilePath() != null) { + evioAdapter = new EvioEventAdapter(new EvioFileSource(new File(config.getFilePath()))); } else { throw new IllegalArgumentException("Configuration is missing a file path."); } - // Using an LCIO file? - } else if (config.sourceType.equals(DataSourceType.LCIO_FILE)) { - if (config.filePath != null) + // Using an LCIO file? + } else if (config.getDataSourceType().equals(DataSourceType.LCIO_FILE)) { + if (config.getFilePath() != null) { try { - lcioAdapter = new LcioEventAdapter(new LCIOEventSource(new File(config.filePath))); - } catch (IOException e) { + lcioAdapter = new LcioEventAdapter(new LCIOEventSource(new File(config.getFilePath()))); + } catch (final IOException e) { throw new RuntimeException("Error configuring LCIOEventSource.", e); } - else + } else { throw new IllegalArgumentException("Configuration is missing a file path."); - } - } - + } + } + } + // Configure ET system. - if (config.sourceType == DataSourceType.ET_SERVER) { + if (config.getDataSourceType() == DataSourceType.ET_SERVER) { addAdapter(etAdapter); } - + // Configure EVIO processing. - if (config.processingStage.ordinal() >= ProcessingStage.EVIO.ordinal()) { - if (config.sourceType.ordinal() <= DataSourceType.EVIO_FILE.ordinal()) { - if (evioAdapter == null) + if (config.getProcessingStage().ordinal() >= ProcessingStage.EVIO.ordinal()) { + if (config.getDataSourceType().ordinal() <= DataSourceType.EVIO_FILE.ordinal()) { + if (evioAdapter == null) { evioAdapter = new EvioEventAdapter(); + } addAdapter(evioAdapter); } } - + // Configure LCIO processing. - if (config.processingStage.ordinal() >= ProcessingStage.LCIO.ordinal()) { + if (config.getProcessingStage().ordinal() >= ProcessingStage.LCIO.ordinal()) { if (lcioAdapter == null) { lcioAdapter = new LcioEventAdapter(); } addAdapter(lcioAdapter); - if (config.eventBuilder != null) { - lcioAdapter.setLCSimEventBuilder(config.eventBuilder); + if (config.getLCSimEventBuilder() != null) { + lcioAdapter.setLCSimEventBuilder(config.getLCSimEventBuilder()); } else { throw new IllegalArgumentException("Missing an LCSimEventBuilder in configuration."); } } - + // Set whether to stop on event processing errors. - setStopOnErrors(config.stopOnErrors); - + setStopOnErrors(config.getStopOnErrors()); + // Set whether to stop on end run EVIO records. - if (evioAdapter != null) - evioAdapter.setStopOnEndRun(config.stopOnEndRun); - + if (evioAdapter != null) { + evioAdapter.setStopOnEndRun(config.getStopOnEndRun()); + } + // Add EtEventProcessors to loop. if (etAdapter != null) { - for (EtEventProcessor processor : config.etProcessors) { + for (final EtEventProcessor processor : config.getEtProcessors()) { etAdapter.addProcessor(processor); } } - + // Add EvioEventProcessors to loop. if (evioAdapter != null) { - for (EvioEventProcessor processor : config.evioProcessors) { + for (final EvioEventProcessor processor : config.getEvioProcessors()) { evioAdapter.addProcessor(processor); } } - + // Add Drivers to loop. if (lcioAdapter != null) { - for (Driver driver : config.drivers) { + for (final Driver driver : config.getDrivers()) { lcioAdapter.addDriver(driver); } } - + // Add CompositeLoopAdapter which should execute last. addAdapter(compositeAdapter); - + // Add CompositeRecordProcessors to loop. - for (CompositeRecordProcessor processor : config.compositeProcessors) { + for (final CompositeRecordProcessor processor : config.getCompositeProcessors()) { compositeAdapter.addProcessor(processor); } - - if (config.supplyLcioEvents) { - addAdapter(new LcioEventSupplier(config.timeout, config.maxQueueSize)); - } - + + if (config.getSupplyLcioEvents()) { + addAdapter(new LcioEventSupplier(config.getTimeout(), config.getMaxQueueSize())); + } + // Max records was set? - if (config.maxRecords != -1) { - compositeAdapter.addProcessor(new MaxRecordsProcessor(config.maxRecords)); - } - } - - public List<CompositeLoopAdapter> getCompositeLoopAdapters() { - return adapters; - } -} + if (config.getMaxRecords() != -1) { + compositeAdapter.addProcessor(new MaxRecordsProcessor(config.getMaxRecords())); + } + } + + /** + * Set the configuration of the loop. + * <p> + * For this class, the <code>object</code> should have the type {@link CompositeLoopConfiguration}. + * + * @param object the configuration object + */ + @Override + public void setConfiguration(final Object object) { + if (object instanceof CompositeLoopConfiguration) { + setCompositeLoopConfiguration((CompositeLoopConfiguration) object); + } else { + throw new IllegalArgumentException("Wrong type of object to configure CompositeLoop: " + + object.getClass().getCanonicalName()); + } + } + + /** + * Set the <code>RecordSource</code> which provides <code>CompositeRecord</code> objects. + * + * @param source the record source + */ + @Override + public void setRecordSource(final RecordSource source) { + if (!source.getRecordClass().isAssignableFrom(CompositeRecord.class)) { + throw new IllegalArgumentException("The RecordSource has the wrong class."); + } + super.setRecordSource(source); + } + + /** + * Set to <code>true</code> in order to have this loop stop on all event processing errors. + * <p> + * Certain types of fatal errors will never be ignored regardless of this setting. + * + * @param stopOnErrors <code>true</code> for this loop to stop on errors + */ + public void setStopOnErrors(final boolean stopOnErrors) { + this.stopOnErrors = stopOnErrors; + } +} Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoopAdapter.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoopAdapter.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoopAdapter.java Mon Apr 13 17:23:55 2015 @@ -11,59 +11,71 @@ /** * Adapter for listening on the {@link CompositeLoop} for records and loop events. - * Classes that should be part of an "event processing chain" implemented by the - * {@link CompositeLoop} should extend this API in order to receive {@link CompositeRecord} - * objects that can be modified. + * <p> + * Classes that should be part of an event processing chain implemented by the {@link CompositeLoop} should extend this + * API in order to receive {@link CompositeRecord} objects that can be read or modified. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public class CompositeLoopAdapter extends AbstractLoopListener implements RecordListener { - List<CompositeRecordProcessor> processors = new ArrayList<CompositeRecordProcessor>(); + /** + * The list of processors that will be activated for each record this adapter receives. + */ + private final List<CompositeRecordProcessor> processors = new ArrayList<CompositeRecordProcessor>(); /** - * Add a <tt>CompositeRecordProcessor</tt> that will listen to this loop. - * @param processor The composite record processor to add. + * Add a <code>CompositeRecordProcessor</code> that will process records from the loop as they are received by the + * adapter. + * + * @param processor the record processor to add */ - public void addProcessor(CompositeRecordProcessor processor) { - processors.add(processor); + public void addProcessor(final CompositeRecordProcessor processor) { + this.processors.add(processor); } - + /** - * Callback for loop finish event. - * @param loopEvent + * Action for loop finish event. + * + * @param loopEvent the <code>LoopEvent</code> with information about record processing session */ - public void finish(LoopEvent loopEvent) { - //System.out.println(this.getClass().getCanonicalName() + ".finish"); + @Override + public void finish(final LoopEvent loopEvent) { + // System.out.println(this.getClass().getCanonicalName() + ".finish"); // Call end job hook on all processors. - for (CompositeRecordProcessor processor : processors) { + for (final CompositeRecordProcessor processor : this.processors) { processor.endJob(); } } - + /** - * 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(); - } - } - - /** - * Process one record. - * @param record + * Process one record with this adapter. + * + * @param record the record to process */ @Override - public void recordSupplied(RecordEvent record) { - for (CompositeRecordProcessor processor : processors) { + public void recordSupplied(final RecordEvent record) { + for (final CompositeRecordProcessor processor : this.processors) { try { // Activate the processing step on the CompositeRecord. processor.process((CompositeRecord) record.getRecord()); - } catch (Exception e) { + } catch (final Exception e) { // Throw the processing error so the loop can perform proper handling of it. throw new RecordProcessingException("Exception occurred during record processing.", e); } } - } + } + + /** + * Start event processing which will call {@link CompositeRecordProcessor#startJob()} on all the registered + * processors. + * + * @param loopEvent the <code>LoopEvent</code> which has record processing information about the session + */ + @Override + public void start(final LoopEvent loopEvent) { + for (final CompositeRecordProcessor processor : this.processors) { + processor.startJob(); + } + } } Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoopConfiguration.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoopConfiguration.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeLoopConfiguration.java Mon Apr 13 17:23:55 2015 @@ -13,215 +13,422 @@ import org.lcsim.util.Driver; /** - * A configuration object for the {@link CompositeLoop}. - * - * The instance variables are readable within the package, - * e.g. by {@link CompositeLoop}, but their values must be - * set through the public set methods when the class is - * used outside its package. - * - * Depending on how this object is setup, some arguments - * may end up being ignored (e.g. setting a file path + * A configuration object for the {@link CompositeLoop}. The instance variables are readable within the package, e.g. by + * {@link CompositeLoop}, but their values must be set through the public set methods when the class is used outside its + * package. Depending on how this object is setup, some arguments may end up being ignored (e.g. setting a file path * when actually using an ET server, etc.). + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ // TODO: Add lcsim steering setting that uses JobControlManager to create Driver list. -public class CompositeLoopConfiguration { - - boolean stopOnErrors = true; - boolean stopOnEndRun = true; - - long maxRecords = -1; - - DataSourceType sourceType = DataSourceType.ET_SERVER; - ProcessingStage processingStage = ProcessingStage.LCIO; - - String filePath = null; - EtConnection connection = null; - RecordSource recordSource = null; - LCSimEventBuilder eventBuilder = null; - - // Event processors. - List<EvioEventProcessor> evioProcessors = new ArrayList<EvioEventProcessor>(); - List<Driver> drivers = new ArrayList<Driver>(); - List<CompositeRecordProcessor> compositeProcessors = new ArrayList<CompositeRecordProcessor>(); - List<EtEventProcessor> etProcessors = new ArrayList<EtEventProcessor>(); - - // Configuration for supplying LCIO events to JAS3 Studio. - boolean supplyLcioEvents; - int maxQueueSize = -1; - long timeout = -1L; - - /** - * Set the full path to a file being used as an event source. - * This is ignored if the ET system is being used. - * @param filePath The full path to a file. +public final class CompositeLoopConfiguration { + + /** + * List of composite record processors. + */ + private final List<CompositeRecordProcessor> compositeProcessors = new ArrayList<CompositeRecordProcessor>(); + + /** + * The ET connection which will be null if not using an ET system. + */ + private EtConnection connection = null; + + /** + * The list of LCSim Drivers. + */ + private final List<Driver> drivers = new ArrayList<Driver>(); + + /** + * The list of ET processors. + */ + private final List<EtEventProcessor> etProcessors = new ArrayList<EtEventProcessor>(); + + /** + * The LCSim event builder for creating LCIO events from EVIO (can be null). + */ + private LCSimEventBuilder eventBuilder = null; + + /** + * The list of EVIO processors. + */ + private final List<EvioEventProcessor> evioProcessors = new ArrayList<EvioEventProcessor>(); + + /** + * Path to a file source. + */ + private String filePath = null; + + /** + * The maximum queue size if using an LCIO record queue. + */ + private int maxQueueSize = -1; + + /** + * The maximum number of records to process (-1 for unlimited). + */ + private long maxRecords = -1; + + /** + * The processing stage to execute (all prior stages will be included). + */ + private ProcessingStage processingStage = ProcessingStage.LCIO; + + /** + * The record source for the loop. + */ + private RecordSource recordSource = null; + + /** + * The data source type which defaults to an ET system. + */ + private DataSourceType sourceType = DataSourceType.ET_SERVER; + + /** + * Flag for stopping the event processing on end of run. + */ + private boolean stopOnEndRun = true; + + /** + * Flag for stopping the event processing on errors. + */ + private boolean stopOnErrors = true; + + /** + * Flag to enable supplying events to the JAS3 record source lookup system. + */ + private boolean supplyLcioEvents; + + /** + * The timeout on the LCIO record queue in milliseconds, if applicable. + */ + private long timeout = -1L; + + /** + * Add a {@link org.hps.record.composite.CompositeRecordProcessor} to the loop. + * + * @param processor The CompositeRecordProcessor. * @return This object. */ - public CompositeLoopConfiguration setFilePath(String filePath) { - this.filePath = filePath; - return this; - } - - /** - * Set the ET connection parameters. - * This is ignored if using direct file streaming. - * @param connection The ET connection parameters. + public CompositeLoopConfiguration add(final CompositeRecordProcessor processor) { + this.compositeProcessors.add(processor); + return this; + } + + /** + * Add an org.lcsim <code>Driver</code> to the loop. + * + * @param processor The Driver. * @return This object. */ - public CompositeLoopConfiguration setEtConnection(EtConnection connection) { - this.connection = connection; - return this; - } - - /** - * Set the data source type e.g. ET server, EVIO file or LCIO file. - * @param sourceType The data source type. - * @return This object. - */ - public CompositeLoopConfiguration setDataSourceType(DataSourceType sourceType) { - this.sourceType = sourceType; - return this; - } - - /** - * Set the processing stage to include i.e. ET only, ET to EVIO, or EVIO to LCIO. - * This may be ignored if the argument does not make sense given the - * {@link org.hps.record.enums.DataSourceType} of this configuration. - * @param processingStage The processing stage to include in the record chaining. - * @return This object. - */ - public CompositeLoopConfiguration setProcessingStage(ProcessingStage processingStage) { - this.processingStage = processingStage; - return this; - } - - /** - * Set directly the <code>RecordSource</code> that will supply records. - * @param recordSource The <code>RecordSource</code> that will supply records. - * @return This object. - */ - public CompositeLoopConfiguration setRecordSource(RecordSource recordSource) { - this.recordSource = recordSource; - return this; - } - - /** - * Set the <code>LCSimEventBuilder</code> that will be used to translate from raw EVIO - * events to LCIO. - * - * The detector name will be set on this object from within {@link CompositeLoop}. - * - * @param eventBuilder The LCSimEventBuilder object. - * @return This object. - */ - public CompositeLoopConfiguration setLCSimEventBuilder(LCSimEventBuilder eventBuilder) { - this.eventBuilder = eventBuilder; - return this; - } - - /** - * Set whether the loop will stop when event processing errors occur. - * Certain types of errors are considered fatal or are used to control - * the loop and will never be ignored (e.g. ET system errors, etc.). - * @param stopOnErrors True to stop the loop when errors occur. - * @return This object. - */ - public CompositeLoopConfiguration setStopOnErrors(boolean stopOnErrors) { - this.stopOnErrors = stopOnErrors; - return this; - } - - /** - * Set whether loop will stop when an end of run record is encountered - * e.g. from an EvioEvent. - * @param stopOnEndRun True to stop on end of run. - * @return This object. - */ - public CompositeLoopConfiguration setStopOnEndRun(boolean stopOnEndRun) { - this.stopOnEndRun = stopOnEndRun; - return this; - } - - /** - * Set the maximum number of records to run. - * @param maxRecords - * @return - */ - public CompositeLoopConfiguration setMaxRecords(long maxRecords) { - if (maxRecords < 1) - throw new IllegalArgumentException("Invalid maxRecords value: " + maxRecords); - this.maxRecords = maxRecords; - return this; - } - - /** - * Set whether to supply LCIO events to a DataSource that will automatically - * register itself to JAS3 in order to drive Wired, the LCSim Event Browser, etc. - * @param supplyLcioEvents True to supply LCIO events to JAS3. - * @return This object. - */ - public CompositeLoopConfiguration setSupplyLcioEvents(boolean supplyLcioEvents) { - this.supplyLcioEvents = supplyLcioEvents; - return this; - } - - /** - * Set the max queue size for the LCIO DataSource that hooks into JAS3. - * @param maxQueueSize The maximum queue size or -1 for unlimited. - * @return This object. - */ - public CompositeLoopConfiguration setMaxQueueSize(int maxQueueSize) { - this.maxQueueSize = maxQueueSize; - return this; - } - - /** - * Set the timeout for calling <code>next</code> on the LCIO record queue. - * @param timeout The timeout in milliseconds. - * @return This object. - */ - public CompositeLoopConfiguration setTimeout(long timeout) { - this.timeout = timeout; - return this; - } - + public CompositeLoopConfiguration add(final Driver processor) { + this.drivers.add(processor); + return this; + } + /** * Add an {@link org.hps.record.et.EtEventProcessor} to the loop. + * * @param processor The EtEventProcessor. * @return This object. */ - public CompositeLoopConfiguration add(EtEventProcessor processor) { - etProcessors.add(processor); - return this; - } - + public CompositeLoopConfiguration add(final EtEventProcessor processor) { + this.etProcessors.add(processor); + return this; + } + /** * Add an {@link org.hps.record.evio.EvioEventProcessor} to the loop. + * * @param processor The EvioEventProcessor. * @return This object. */ - public CompositeLoopConfiguration add(EvioEventProcessor processor) { - evioProcessors.add(processor); - return this; - } - - /** - * Add an org.lcsim <code>Driver</code> to the loop. - * @param processor The Driver. - * @return This object. - */ - public CompositeLoopConfiguration add(Driver processor) { - drivers.add(processor); - return this; - } - - /** - * Add a {@link org.hps.record.composite.CompositeRecordProcessor} to the loop. - * @param processor The CompositeRecordProcessor. - * @return This object. - */ - public CompositeLoopConfiguration add(CompositeRecordProcessor processor) { - compositeProcessors.add(processor); + public CompositeLoopConfiguration add(final EvioEventProcessor processor) { + this.evioProcessors.add(processor); + return this; + } + + /** + * Get the list of composite record processors. + * + * @return the list of composite record processors + */ + List<CompositeRecordProcessor> getCompositeProcessors() { + return this.compositeProcessors; + } + + /** + * Get the data source type (EVIO, LCIO or ET). + * + * @return the data source type + */ + DataSourceType getDataSourceType() { + return this.sourceType; + } + + /** + * Get the list of Drivers to add to the loop. + * + * @return the list of Drivers + */ + List<Driver> getDrivers() { + return this.drivers; + } + + /** + * Get the ET connection (can be <code>null</code>). + * + * @return the ET connection + */ + EtConnection getEtConnection() { + return this.connection; + } + + /** + * Get the list of ET event processors. + * + * @return the list of ET event processors + */ + List<EtEventProcessor> getEtProcessors() { + return this.etProcessors; + } + + /** + * Get the list of EVIO event processors. + * + * @return the list of EVIO event processors + */ + List<EvioEventProcessor> getEvioProcessors() { + return this.evioProcessors; + } + + /** + * Get the file path of a data source if using a file based source (can be null). + * + * @return the file path of a data source + */ + String getFilePath() { + return this.filePath; + } + + /** + * Get the builder for creating LCIO events from EVIO. + * + * @return the event builder + */ + LCSimEventBuilder getLCSimEventBuilder() { + return this.eventBuilder; + } + + /** + * Get the maximum size of the LCIO record queue. + * + * @return the maximum size of the LCIO record queue + */ + int getMaxQueueSize() { + return this.maxQueueSize; + } + + /** + * Get the maximum number of records to process. + * + * @return the maximum number of records to process + */ + long getMaxRecords() { + return this.maxRecords; + } + + /** + * Get the processing stage to execute (all prior stages will be executed as well). + * + * @return the processing stage to execute including prior stages + */ + ProcessingStage getProcessingStage() { + return this.processingStage; + } + + /** + * Get the record source. + * + * @return the record source + */ + RecordSource getRecordSource() { + return this.recordSource; + } + + /** + * Returns <code>true</code> if stop on end run is enabled. + * + * @return <code>true</code> if stop on end run is enabled + */ + boolean getStopOnEndRun() { + return this.stopOnEndRun; + } + + /** + * Returns <code>true</code> if stop on errors is enabled. + * + * @return <code>true</code> if stop on errors is enabled + */ + boolean getStopOnErrors() { + return this.stopOnErrors; + } + + /** + * Returns <code>true</code> if supplying LCIO events to JAS3 is enabled. + * + * @return <code>true</code> if supplying LCIO events to JAS3 is enabled + */ + boolean getSupplyLcioEvents() { + return this.supplyLcioEvents; + } + + /** + * Get the LCIO event queue timeout in milliseconds. + * + * @return the LCIO event queue timeout in milliseconds + */ + long getTimeout() { + return this.timeout; + } + + /** + * Set the data source type e.g. ET server, EVIO file or LCIO file. + * + * @param sourceType the data source type + * @return this object + */ + public CompositeLoopConfiguration setDataSourceType(final DataSourceType sourceType) { + this.sourceType = sourceType; + return this; + } + + /** + * Set the ET connection parameters. This is ignored if using direct file streaming. + * + * @param connection the ET connection parameters + * @return this object + */ + public CompositeLoopConfiguration setEtConnection(final EtConnection connection) { + this.connection = connection; + return this; + } + + /** + * Set the full path to a file being used as an event source. This is ignored if the ET system is being used. + * + * @param filePath the full path to a file + * @return this object + */ + public CompositeLoopConfiguration setFilePath(final String filePath) { + this.filePath = filePath; + return this; + } + + /** + * Set the <code>LCSimEventBuilder</code> that will be used to translate from raw EVIO events to LCIO. The detector + * name will be set on this object from within {@link CompositeLoop}. + * + * @param eventBuilder the LCSimEventBuilder object + * @return this object + */ + public CompositeLoopConfiguration setLCSimEventBuilder(final LCSimEventBuilder eventBuilder) { + this.eventBuilder = eventBuilder; + return this; + } + + /** + * Set the max queue size for the LCIO DataSource that hooks into JAS3. + * + * @param maxQueueSize the maximum queue size or -1 for unlimited + * @return this object + */ + public CompositeLoopConfiguration setMaxQueueSize(final int maxQueueSize) { + this.maxQueueSize = maxQueueSize; + return this; + } + + /** + * Set the maximum number of records. + * + * @param maxRecords the maximum number of records + * @return the maximum number of records + */ + public CompositeLoopConfiguration setMaxRecords(final long maxRecords) { + if (maxRecords < 1) { + throw new IllegalArgumentException("Invalid maxRecords value: " + maxRecords); + } + this.maxRecords = maxRecords; + return this; + } + + /** + * Set the processing stage to include i.e. ET only, ET to EVIO, or all three. + * <p> + * This may be ignored if the argument does not make sense given the {@link org.hps.record.enums.DataSourceType} of + * this configuration. + * + * @param processingStage the processing stages to execute + * @return this object + */ + public CompositeLoopConfiguration setProcessingStage(final ProcessingStage processingStage) { + this.processingStage = processingStage; + return this; + } + + /** + * Set directly the <code>RecordSource</code> that will supply records. + * + * @param recordSource the <code>RecordSource</code> that will supply records + * @return this object + */ + public CompositeLoopConfiguration setRecordSource(final RecordSource recordSource) { + this.recordSource = recordSource; + return this; + } + + /** + * Set whether loop will stop when an end of run record is encountered e.g. from an EvioEvent. + * + * @param stopOnEndRun <code>true</code> to stop on end of run + * @return this object + */ + public CompositeLoopConfiguration setStopOnEndRun(final boolean stopOnEndRun) { + this.stopOnEndRun = stopOnEndRun; + return this; + } + + /** + * Set whether the loop will stop when event processing errors occur. Certain types of errors are considered fatal + * or are used to control the loop and will never be ignored (e.g. ET system errors, etc.). + * + * @param stopOnErrors <code>true</code> to stop the loop when errors occur + * @return this object + */ + public CompositeLoopConfiguration setStopOnErrors(final boolean stopOnErrors) { + this.stopOnErrors = stopOnErrors; + return this; + } + + /** + * Set whether to supply LCIO events to a DataSource that will automatically register itself to JAS3 in order to + * activate Wired, the LCSim Event Browser, etc. + * + * @param supplyLcioEvents <code>true</code> to supply LCIO events to JAS3 + * @return this object + */ + public CompositeLoopConfiguration setSupplyLcioEvents(final boolean supplyLcioEvents) { + this.supplyLcioEvents = supplyLcioEvents; + return this; + } + + /** + * Set the timeout when calling <code>next</code> on the LCIO record queue. + * + * @param timeout the timeout in milliseconds + * @return this object + */ + public CompositeLoopConfiguration setTimeout(final long timeout) { + this.timeout = timeout; return this; } } Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecord.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecord.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecord.java Mon Apr 13 17:23:55 2015 @@ -5,97 +5,126 @@ import org.lcsim.event.EventHeader; /** - * This class is used to group together corresponding ET, EVIO and LCIO events - * for use by the {@link CompositeLoop}. The loop's <code>RecordListener</code> - * objects may alter this record by setting references to event objects - * such as an <code>EvioEvent</code>. + * This class is used to group together corresponding ET, EVIO and LCIO events for use by the {@link CompositeLoop}. The + * loop's <code>RecordListener</code> objects may alter this record by setting references to event objects such as an + * <code>EvioEvent</code>. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public final class CompositeRecord { - - EtEvent etEvent; - EvioEvent evioEvent; - EventHeader lcioEvent; - - int sequenceNumber = -1; - int eventNumber = -1; - + + /** + * The ET event. + */ + private EtEvent etEvent; + + /** + * The event number. + */ + private int eventNumber = -1; + + /** + * The EVIO event. + */ + private EvioEvent evioEvent; + + /** + * The LCIO/LCSim event. + */ + private EventHeader lcioEvent; + + /** + * The event's sequence number. + */ + private int sequenceNumber = -1; + + /** + * Get the <code>EtEvent</code>. + * + * @return the EtEvent + */ + public EtEvent getEtEvent() { + return this.etEvent; + } + + /** + * Get the event number. + * + * @return the event number + */ + public int getEventNumber() { + return this.eventNumber; + } + + /** + * Get the <code>EvioEvent</code>. + * + * @return the EvioEvent + */ + public EvioEvent getEvioEvent() { + return this.evioEvent; + } + + /** + * Get the org.lcsim event. + * + * @return the org.lcsim event + */ + public EventHeader getLcioEvent() { + return this.lcioEvent; + } + + /** + * Get the event sequence number. + * + * @return the event sequence number + */ + public int getSequenceNumber() { + return this.sequenceNumber; + } + + /** + * Set a reference to an <code>EtEvent</code>. + * + * @param etEvent the EtEvent + */ + public void setEtEvent(final EtEvent etEvent) { + this.etEvent = etEvent; + } + + /** + * Set the event number of this record e.g. from EVIO or LCIO. + * + * @param eventNumber the event number of this record + */ + public void setEventNumber(final int eventNumber) { + this.eventNumber = eventNumber; + } + + /** + * Set a reference to an <code>EvioEvent</code>. + * + * @param evioEvent the EvioEvent + */ + public void setEvioEvent(final EvioEvent evioEvent) { + this.evioEvent = evioEvent; + } + + /** + * Set a reference to an org.lcsim LCIO event (EventHeader). + * + * @param lcioEvent the LCIO EventHeader + */ + public void setLcioEvent(final EventHeader lcioEvent) { + this.lcioEvent = lcioEvent; + } + /** * Set the sequence number of this record. - * @param sequenceNumber The sequence number. + * + * @param sequenceNumber the event sequence number */ - public void setSequenceNumber(int sequenceNumber) { + public void setSequenceNumber(final int sequenceNumber) { this.sequenceNumber = sequenceNumber; } - - /** - * Set the event number of this record e.g. from EVIO or LCIO. - * @param eventNumber The event number of this recrod. - */ - public void setEventNumber(int eventNumber) { - this.eventNumber = eventNumber; - } - - /** - * Set a reference to an <code>EtEvent</code>. - * @param etEvent The EtEvent. - */ - public void setEtEvent(EtEvent etEvent) { - this.etEvent = etEvent; - } - - /** - * Set a reference to an <code>EvioEvent</code>. - * @param evioEvent The EvioEvent. - */ - public void setEvioEvent(EvioEvent evioEvent) { - this.evioEvent = evioEvent; - } - - /** - * Set a reference to an org.lcsim LCIO event (EventHeader). - * @param lcioEvent The LCIO EventHeader. - */ - public void setLcioEvent(EventHeader lcioEvent) { - this.lcioEvent = lcioEvent; - } - - /** - * Get the <code>EtEvent</code>. - * @return The EtEvent. - */ - public EtEvent getEtEvent() { - return etEvent; - } - - /** - * Get the <code>EvioEvent</code>. - * @return The EvioEvent. - */ - public EvioEvent getEvioEvent() { - return evioEvent; - } - - /** - * Get the org.lcsim event. - * @return The org.lcsim event. - */ - public EventHeader getLcioEvent() { - return lcioEvent; - } - - /** - * Get the event sequence number. - * @return The event sequence number. - */ - public int getSequenceNumber() { - return sequenceNumber; - } - - /** - * Get the event number. - * @return The event number. - */ - public int getEventNumber() { - return eventNumber; - } } Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecordProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecordProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecordProcessor.java Mon Apr 13 17:23:55 2015 @@ -3,8 +3,9 @@ import org.hps.record.AbstractRecordProcessor; /** - * An <code>EventProcessor</code> implementation for processing <code>CompositeRecord</code> - * records. + * An <code>EventProcessor</code> implementation for processing <code>CompositeRecord</code> records. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public abstract class CompositeRecordProcessor extends AbstractRecordProcessor<CompositeRecord> { } Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecordSource.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecordSource.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/CompositeRecordSource.java Mon Apr 13 17:23:55 2015 @@ -6,49 +6,61 @@ import org.freehep.record.source.NoSuchRecordException; /** - * A record source providing <code>CompositeRecord</code> objects - * that can be accessed and/or modified by <code>RecordListener</code> - * objects on the loop. This is essentially a minimal implementation - * that does not support advanced operations like rewind or index. + * A record source providing <code>CompositeRecord</code> objects that can be accessed and/or modified by + * <code>RecordListener</code> objects on the loop. This is essentially a minimal implementation that does not support + * advanced operations like rewind or index. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public final class CompositeRecordSource extends AbstractRecordSource { + /** + * The current record. + */ CompositeRecord currentRecord; + + /** + * The sequence number. + */ int sequenceNumber = 1; - + + /** + * Get the current {@link CompositeRecord}. + * + * @return the current CompositeRecord + */ + @Override + public Object getCurrentRecord() throws IOException { + return this.currentRecord; + } + + /** + * Return <code>true</code> if source has a current record. + * + * @return <code>true</code> if this source has a current record + */ + @Override + public boolean hasCurrent() { + return this.currentRecord != null; + } + /** * Load the next record which is then accessible using {@link #getCurrentRecord()}. */ + @Override public void next() throws IOException, NoSuchRecordException { - currentRecord = new CompositeRecord(); - currentRecord.setSequenceNumber(sequenceNumber); - ++sequenceNumber; + this.currentRecord = new CompositeRecord(); + this.currentRecord.setSequenceNumber(this.sequenceNumber); + ++this.sequenceNumber; } - + /** - * Get the current {@link CompositeRecord}. - * @return The current CompositeRecord. - */ - @Override - public Object getCurrentRecord() throws IOException { - return currentRecord; - } - - /** - * Get whether this source supports the next command (true). - * @return Whether this source supports the next command. + * Return <code>true</code> to indicate next record capability is supported. + * + * @return <code>true</code> to indicate next record capability is supported */ @Override public boolean supportsNext() { return true; } - - /** - * Get whether this source has a current record. - * @return Whether this source has a current record. - */ - @Override - public boolean hasCurrent() { - return currentRecord != null; - } } Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/EtEventAdapter.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/EtEventAdapter.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/EtEventAdapter.java Mon Apr 13 17:23:55 2015 @@ -10,34 +10,42 @@ /** * An adapter for directly using the CompositeLoop to supply and process EtEvents. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public class EtEventAdapter extends RecordProcessorAdapter<EtEvent> { - EtEventSource source; - /** - * Constructor with an {@link org.hps.record.et.EtEventSource} - * that supplies <code>EtEvent</code> records through a network - * ET server. - * @param source The event source. + * The ET event source. */ - public EtEventAdapter(EtEventSource source) { + private final EtEventSource source; + + /** + * Constructor with an {@link org.hps.record.et.EtEventSource} that supplies <code>EtEvent</code> records through a + * network ET server. + * + * @param source the event source + */ + public EtEventAdapter(final EtEventSource source) { this.source = source; } - + /** - * Process one record which will get the next <code>EtEvent</code> - * from the source and set a reference to it on the {@link CompositeRecord}. + * Process one record which will get the next <code>EtEvent</code> from the source and set a reference to it on the + * {@link CompositeRecord}. + * + * @param record the current composite record */ - public void recordSupplied(RecordEvent record) { - CompositeRecord compositeRecord = (CompositeRecord) record.getRecord(); + @Override + public void recordSupplied(final RecordEvent record) { + final CompositeRecord compositeRecord = (CompositeRecord) record.getRecord(); try { - source.next(); - if (source.getCurrentRecord() != null) { - compositeRecord.setEtEvent((EtEvent) source.getCurrentRecord()); + this.source.next(); + if (this.source.getCurrentRecord() != null) { + compositeRecord.setEtEvent((EtEvent) this.source.getCurrentRecord()); } else { throw new NoSuchRecordException("No current ET record available from source."); - } + } process(compositeRecord.getEtEvent()); } catch (IOException | NoSuchRecordException e) { throw new RecordProcessingException("Error processing ET record.", e); Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/EventProcessingThread.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/EventProcessingThread.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/EventProcessingThread.java Mon Apr 13 17:23:55 2015 @@ -4,49 +4,55 @@ /** * Class for running the {@link CompositeLoop} on a separate thread. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public final class EventProcessingThread extends Thread { - - CompositeLoop loop; - + /** - * Constructor requiring the loop object. - * @param loop The loop object. + * The composite record loop. */ - public EventProcessingThread(CompositeLoop loop) { + private final CompositeLoop loop; + + /** + * Class constructor, requiring the loop object for record processing. + * + * @param loop the loop object + */ + public EventProcessingThread(final CompositeLoop loop) { super("EventProcessingThread"); this.loop = loop; } - + /** * Run this thread, which will process records until the loop is done. */ @Override - public void run() { - + public void run() { + // Flag that is turned on when looping starts. boolean started = false; - + // Keep looping until the event processing is done. - while (true) { - + while (true) { + // If the loop was started and now is in the IDLE state, it means // that STOP was executed, so break from the processing while loop. - if (started && loop.getState().equals(RecordLoop.State.IDLE)) { + if (started && this.loop.getState().equals(RecordLoop.State.IDLE)) { // Stop record processing. break; } - - // Is the processing unpaused? - if (!loop.isPaused()) { - + + // Is the processing not paused? + if (!this.loop.isPaused()) { + // Set a flag to indicate that looping has started. started = true; - + // Loop until done, error occurs, or pause is requested. - // FIXME: The maximum number of records should be used here. - loop.loop(-1); - } + // FIXME: The maximum number of records should be used here instead. + this.loop.loop(-1); + } } } -} +} Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/EvioEventAdapter.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/EvioEventAdapter.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/EvioEventAdapter.java Mon Apr 13 17:23:55 2015 @@ -18,40 +18,57 @@ /** * An adapter for directly using the CompositeLoop to supply and process EvioEvents. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public class EvioEventAdapter extends RecordProcessorAdapter<EvioEvent> { - - AbstractRecordSource source; - boolean stopOnEndRun = true; - + /** - * Constructor that takes a record source. - * @param source The record source. + * The record source. */ - public EvioEventAdapter(AbstractRecordSource source) { - this.source = source; - } - + private AbstractRecordSource source; + /** - * No argument constructor for when ET will be converted to EVIO. + * Flag to stop processing when an END event is received. + */ + private boolean stopOnEndRun = true; + + /** + * No argument constructor, for when ET events will be converted to EVIO. */ public EvioEventAdapter() { } - + /** - * Set whether to stop when end run records are received. - * @param stopOnEndRun True to stop on end run EVIO records. + * Constructor that takes a record source. + * + * @param source the record source */ - public void setStopOnEndRun(boolean stopOnEndRun) { - this.stopOnEndRun = stopOnEndRun; + public EvioEventAdapter(final AbstractRecordSource source) { + this.source = source; } - + /** - * Process one record which will create an <code>EvioEvent</code> or - * get it from the source and set a reference to it on the {@link CompositeRecord}. + * Create an <code>EvioEvent</code> from an <code>EtEvent</code> byte buffer. + * + * @param etEvent the input <code>EtEvent</code> + * @return the <code>EvioEvent</code> created from the <code>EtEvent</code> + * @throws IOException if there is an IO problem from EVIO + * @throws EvioException if there is any EVIO related error when creating the event + * @throws BufferUnderflowException if there isn't enough data in the byte buffer */ - public void recordSupplied(RecordEvent record) { - CompositeRecord compositeRecord = (CompositeRecord) record.getRecord(); + private EvioEvent createEvioEvent(final EtEvent etEvent) throws IOException, EvioException, + BufferUnderflowException { + return new EvioReader(etEvent.getDataBuffer()).parseNextEvent(); + } + + /** + * Process one record which will create an <code>EvioEvent</code> or get it from the source and set a reference to + * it on the {@link CompositeRecord}. + */ + @Override + public void recordSupplied(final RecordEvent record) { + final CompositeRecord compositeRecord = (CompositeRecord) record.getRecord(); try { EvioEvent evioEvent; // Using ET system? @@ -64,10 +81,10 @@ throw new RecordProcessingException("Failed to create EvioEvent from EtEvent.", e); } } else { - // Load the next record from the EVIO record source. - if (source.hasNext()) { - source.next(); - evioEvent = (EvioEvent)source.getCurrentRecord(); + // Load the next record from the EVIO record source. + if (this.source.hasNext()) { + this.source.next(); + evioEvent = (EvioEvent) this.source.getCurrentRecord(); } else { throw new NoSuchRecordException("EVIO event source has no more records."); } @@ -77,65 +94,64 @@ // Throw an error because EvioEvent was not created. throw new NoSuchRecordException("Failed to get next EVIO record."); } - + // Set event number on the EvioEvent. setEventNumber(evioEvent); - + // Is pre start event? if (EvioEventUtilities.isPreStartEvent(evioEvent)) { // Activate start of run hook on processors. startRun(evioEvent); - // Is end run event? + // Is end run event? } else if (EvioEventUtilities.isEndEvent(evioEvent)) { // Activate end of run hook on processors. endRun(evioEvent); - + // Stop on end run enabled? - if (stopOnEndRun) { + if (this.stopOnEndRun) { // Throw exception to stop processing from end run. throw new EndRunException("EVIO end event received.", evioEvent.getIntData()[1]); - } - // Is physics event? + } + // Is physics event? } else if (EvioEventUtilities.isPhysicsEvent(evioEvent)) { // Process a single physics EvioEvent. process(evioEvent); } - + // Set EvioEvent on CompositeRecord. compositeRecord.setEvioEvent(evioEvent); } catch (IOException | NoSuchRecordException e) { throw new RecordProcessingException("No next EVIO record available from source.", e); - } + } } - - /** - * Create an EvioEvent from an EtEvent byte buffer. - * @param etEvent The input EtEvent. - * @return The EvioEvent created from the EtEvent. - * @throws IOException - * @throws EvioException - * @throws BufferUnderflowException - */ - private EvioEvent createEvioEvent(EtEvent etEvent) - throws IOException, EvioException, BufferUnderflowException { - return (new EvioReader(etEvent.getDataBuffer())).parseNextEvent(); - } - + /** * Set the EVIO event number manually from the event ID bank. - * @param evioEvent The <tt>EvioEvent</tt> on which to set the event number. + * + * @param evioEvent the <code>EvioEvent</code> on which to set the event number */ - private void setEventNumber(EvioEvent evioEvent) { + private void setEventNumber(final EvioEvent evioEvent) { int eventNumber = -1; - if (evioEvent.getChildren() != null) { - for (BaseStructure bank : evioEvent.getChildren()) { + if (evioEvent.getChildrenList() != null) { + for (final BaseStructure bank : evioEvent.getChildrenList()) { if (bank.getHeader().getTag() == EvioEventConstants.EVENTID_BANK_TAG) { eventNumber = bank.getIntData()[0]; break; } } } - if (eventNumber != -1) + if (eventNumber != -1) { evioEvent.setEventNumber(eventNumber); - } + } + } + + /** + * Returns <code>true</code> if processing should be stopped when end of run occurs, e.g. from an EVIO END record + * being received. + * + * @param stopOnEndRun <code>true</code> to stop after EVIO END records are received + */ + public final void setStopOnEndRun(final boolean stopOnEndRun) { + this.stopOnEndRun = stopOnEndRun; + } } Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/LcioEventAdapter.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/LcioEventAdapter.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/LcioEventAdapter.java Mon Apr 13 17:23:55 2015 @@ -15,85 +15,106 @@ import org.lcsim.util.DriverAdapter; /** - * An adapter to supply and process LCSim EventHeader objects using - * an (optional) LCSimEventBuilder and the existing DriverAdapter class. + * An adapter to supply and process LCSim EventHeader objects using an (optional) LCSimEventBuilder and the existing + * DriverAdapter class. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public class LcioEventAdapter extends CompositeLoopAdapter { - DriverAdapter drivers; - Driver top = new Driver(); - LCSimEventBuilder builder; - AbstractRecordSource source; + /** + * The builder for creating LCIO from EVIO. + */ + private LCSimEventBuilder builder; /** - * Constructor taking a record source which should supply - * LCSim LCIO events. - * @param source + * A list of Drivers to execute on the LCIO events. */ - public LcioEventAdapter(AbstractRecordSource source) { - this.source = source; - drivers = new DriverAdapter(top); + private final DriverAdapter drivers; + + /** + * The record source. + */ + private AbstractRecordSource source; + + /** + * A top level Driver for executing a number of other Drivers as children. + */ + private final Driver top = new Driver(); + + /** + * Class Constructor with no arguments. + * <p> + * This is used when the {@link CompositeRecord} should supply <code>EvioEvent</code> objects for the builder. + */ + public LcioEventAdapter() { + this.drivers = new DriverAdapter(this.top); } /** - * No argument constructor in which case the {@link CompositeRecord} - * should supply <code>EvioEvent</code> objects for the builder. + * Class constructor. + * <p> + * The provided record source should supply LCIO/LCSim events directly. + * + * @param source the record source of LCIO events */ - public LcioEventAdapter() { - drivers = new DriverAdapter(top); + public LcioEventAdapter(final AbstractRecordSource source) { + this.source = source; + this.drivers = new DriverAdapter(this.top); } /** - * Add an LCSim <code>Driver</code> - * @param driver The Driver to add. + * Add an LCSim <code>Driver</code> to execute. + * + * @param driver the Driver to add */ - public void addDriver(Driver driver) { - top.add(driver); + public void addDriver(final Driver driver) { + this.top.add(driver); } /** - * Set the <code>LCSimEventBuilder</code> that will convert - * from EVIO to LCIO events. - * @param builder + * Activates the <code>endOfData</code> method on the registered <code>Driver</code> objects. */ - public void setLCSimEventBuilder(LCSimEventBuilder builder) { - this.builder = builder; + @Override + public void finish(final LoopEvent loopEvent) { + this.drivers.finish(loopEvent); } /** - * Process a {@link CompositeRecord} which will add an LCSim event - * and activate registered <code>Driver</code> objects. + * Process a {@link CompositeRecord} which will create an LCSim event, add it to the composite record being + * processed, and activate registered the <code>Driver</code> chain. */ - public void recordSupplied(RecordEvent record) { - CompositeRecord compositeRecord = (CompositeRecord) record.getRecord(); + @Override + public void recordSupplied(final RecordEvent record) { + final CompositeRecord compositeRecord = (CompositeRecord) record.getRecord(); EventHeader lcioEvent = null; try { // Is there an EVIO event to use for the conversion to LCIO? if (compositeRecord.getEvioEvent() != null) { // Create the EVIO event. - EvioEvent evioEvent = compositeRecord.getEvioEvent(); - + final EvioEvent evioEvent = compositeRecord.getEvioEvent(); + // Pre-read the event in the builder to get non-physics event information. - builder.readEvioEvent(evioEvent); - + this.builder.readEvioEvent(evioEvent); + // Is this a physics EvioEvent? if (EvioEventUtilities.isPhysicsEvent(evioEvent)) { // Use the builder to create the LCIO event. - lcioEvent = builder.makeLCSimEvent(compositeRecord.getEvioEvent()); + lcioEvent = this.builder.makeLCSimEvent(compositeRecord.getEvioEvent()); } else { // Non-physics events are ignored. - return; + return; } } else { // Try to use the event source to get the next LCIO event. - source.next(); - lcioEvent = (EventHeader) source.getCurrentRecord(); + this.source.next(); + lcioEvent = (EventHeader) this.source.getCurrentRecord(); } - + // Supply the EventHeader to the DriverAdapter. - RecordEvent recordEvent = new RecordEvent(null, lcioEvent); - drivers.recordSupplied(recordEvent); - + final RecordEvent recordEvent = new RecordEvent(null, lcioEvent); + this.drivers.recordSupplied(recordEvent); + // Set the reference to the LCIO event on the CompositeRecord. compositeRecord.setLcioEvent(lcioEvent); } catch (IOException | NoSuchRecordException e) { @@ -102,26 +123,31 @@ } /** - * Activates the <code>endOfData</code> method on the registered - * <code>Driver</code> objects. + * Set the <code>LCSimEventBuilder</code> that will convert from EVIO to LCIO events. + * + * @param builder the LCSim event builder for creating LCIO events from EVIO */ - public void finish(LoopEvent loopEvent) { - drivers.finish(loopEvent); + public void setLCSimEventBuilder(final LCSimEventBuilder builder) { + this.builder = builder; } /** - * Activates the <code>startOfData</code> method on registered - * <code>Driver</code> objects. + * Activates the <code>startOfData</code> method on registered <code>Driver</code> objects. + * + * @param loopEvent the object with loop state information */ - public void start(LoopEvent loopEvent) { - drivers.start(loopEvent); + @Override + public void start(final LoopEvent loopEvent) { + this.drivers.start(loopEvent); } - + /** - * Activates the <code>suspend</code> method on registered - * <code>Driver</code> objects. + * Activates the <code>suspend</code> method on registered <code>Driver</code> objects. + * + * @param loopEvent the object with loop state information */ - public void suspend(LoopEvent loopEvent) { - drivers.suspend(loopEvent); + @Override + public void suspend(final LoopEvent loopEvent) { + this.drivers.suspend(loopEvent); } } Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/LcioEventSupplier.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/LcioEventSupplier.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/LcioEventSupplier.java Mon Apr 13 17:23:55 2015 @@ -1,37 +1,50 @@ package org.hps.record.composite; +import org.freehep.application.Application; import org.freehep.application.studio.Studio; import org.freehep.record.loop.RecordEvent; import org.hps.record.lcio.LcioEventQueue; /** - * This adapter can be used to supply LCIO EventHeader objects to JAS3 - * via a DataSource in order to drive Wired, etc. - * - * @author Jeremy McCormick <[log in to unmask]> + * This is an adapter that can supply LCIO <code>EventHeader</code> objects to JAS3 via a registered + * <code>DataSource</code> in order to activate Wired, the LCSim Event Browser, etc. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public class LcioEventSupplier extends CompositeLoopAdapter { - - LcioEventQueue events; - - LcioEventSupplier(long timeoutMillis, int maxSize) { - events = new LcioEventQueue(timeoutMillis, maxSize); - events.setName(LcioEventSupplier.class.getName()); - Studio studio = (Studio)Studio.getApplication(); + + /** + * The LCIO event queue which supplies records. + */ + private final LcioEventQueue events; + + /** + * Class constructor. + * + * @param timeoutMillis the queue timeout in milliseconds + * @param maxSize the maximum size of the record queue + */ + LcioEventSupplier(final long timeoutMillis, final int maxSize) { + this.events = new LcioEventQueue(timeoutMillis, maxSize); + this.events.setName(LcioEventSupplier.class.getName()); + final Studio studio = (Studio) Application.getApplication(); if (studio != null) { - studio.getLookup().add(events); + studio.getLookup().add(this.events); } } - - public void recordSupplied(RecordEvent record) { - CompositeRecord compositeRecord = (CompositeRecord) record.getRecord(); + + /** + * Process composite records by adding their LCIO event references to the queue in order to supply them to JAS3. + * + * @param record the composite record + */ + @Override + public void recordSupplied(final RecordEvent record) { + final CompositeRecord compositeRecord = (CompositeRecord) record.getRecord(); if (compositeRecord.getLcioEvent() != null) { - System.out.println("LcioEventSupplier - adding event #" + compositeRecord.getLcioEvent().getEventNumber() + " to queue"); - events.addRecord(compositeRecord.getLcioEvent()); + System.out.println("LcioEventSupplier - adding event #" + compositeRecord.getLcioEvent().getEventNumber() + + " to queue"); + this.events.addRecord(compositeRecord.getLcioEvent()); } } - - public LcioEventQueue getLcioEventQueue() { - return events; - } } Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/MaxRecordsProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/MaxRecordsProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/MaxRecordsProcessor.java Mon Apr 13 17:23:55 2015 @@ -4,45 +4,57 @@ import org.hps.record.evio.EvioEventUtilities; /** - * A @{link CompositeProcessor} for throwing an error when the - * maximum number of records is reached or exceeded. + * A @{link CompositeProcessor} for throwing an error when the maximum number of records is reached or exceeded. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public class MaxRecordsProcessor extends CompositeRecordProcessor { - - long maxRecords; - long recordsReceived; - + /** - * Constructor with the maximum number of records. - * @param maxRecords The maximum number of records. + * The maximum number of records. */ - public MaxRecordsProcessor(long maxRecords) { + private final long maxRecords; + + /** + * The number of records received. + */ + private long recordsReceived; + + /** + * Class constructor, with the maximum number of records. + * + * @param maxRecords the maximum number of records + */ + public MaxRecordsProcessor(final long maxRecords) { this.maxRecords = maxRecords; } - + /** * Process a record and check if max number of records was reached. - * Only records with certain types are considered in this total, - * which are basically "physics" events when processing LCIO - * or EVIO files. For an ET system without any other record processing, - * all events count towards the total. + * <p> + * Only records with certain types are considered in this total, which are basically "physics" events when + * processing LCIO or EVIO files. For an ET system without any other record processing attached, all events count + * towards the total as it is not easy to tell generically which are physics data events. + * + * @param record the composite record to process */ - public void process(CompositeRecord record) { + @Override + public void process(final CompositeRecord record) { if (record.getLcioEvent() != null) { // All LCSim events count as records. - ++recordsReceived; + ++this.recordsReceived; } else if (record.getEvioEvent() != null) { if (EvioEventUtilities.isPhysicsEvent(record.getEvioEvent())) { // Only EVIO physics events are counted. - ++recordsReceived; + ++this.recordsReceived; } } else { // Otherwise (ET only?) count all records. - ++recordsReceived; - } - if (recordsReceived >= maxRecords) { + ++this.recordsReceived; + } + if (this.recordsReceived >= this.maxRecords) { // Throw exception if max records was reached or exceeded. - throw new MaxRecordsException("Maximum number of records received.", maxRecords); + throw new MaxRecordsException("Maximum number of records received.", this.maxRecords); } } } Modified: java/trunk/record-util/src/main/java/org/hps/record/composite/RecordProcessorAdapter.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/RecordProcessorAdapter.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/RecordProcessorAdapter.java Mon Apr 13 17:23:55 2015 @@ -8,97 +8,107 @@ import org.hps.record.RecordProcessor; /** - * An extension of {@link CompositeLoopAdapter} that has a list of {@link org.hps.record.RecordProcessor} - * objects that are activated in the appropriate hook methods. + * An extension of {@link CompositeLoopAdapter} which has a list of {@link org.hps.record.RecordProcessor} objects that + * are activated in the appropriate hook methods for every event. + * * @param <RecordType> The concrete type of the record being processed. + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public abstract class RecordProcessorAdapter<RecordType> extends CompositeLoopAdapter { - List<RecordProcessor<RecordType>> processors = new ArrayList<RecordProcessor<RecordType>>(); - + /** + * The list of composite record processors. + */ + private final List<RecordProcessor<RecordType>> processors = new ArrayList<RecordProcessor<RecordType>>(); + /** * Add a <code>RecordProcessor</code>. - * @param processor The RecordProcessor to add. + * + * @param processor the <code>RecordProcessor</code> to add */ - public void addProcessor(RecordProcessor<RecordType> processor) { - processors.add(processor); + public void addProcessor(final RecordProcessor<RecordType> processor) { + this.processors.add(processor); } - + /** - * Remove a <code>RecordProcessor</code>. - * @param processor The RecordProcessor to remove. + * Activate the <code>endRun</code> methods of the registered processors. + * + * @param record the current record. */ - public void removeProcessor(RecordProcessor<RecordType> processor) { - processors.remove(processor); - } - - /** - * Activate the <code>startRun</code> methods of the - * registered processors. - * @param record The current record. - */ - public void startRun(RecordType record) { - for (RecordProcessor<RecordType> processor : processors) { - processor.startRun(record); - } - } - - /** - * Activate the <code>endRun</code> methods of the - * registered processors. - * @param record The current record. - */ - public void endRun(RecordType record) { - for (RecordProcessor<RecordType> processor : processors) { + public void endRun(final RecordType record) { + for (final RecordProcessor<RecordType> processor : this.processors) { processor.endRun(record); } } - + /** - * Activate the <code>process</code> methods of the - * registered processors. - * @param record The current record. + * Activate the <code>endJob</code> methods of the registered processors. + * + * @param the <code>LoopEvent</code> which activated <code>finish</code> */ - public void process(RecordType record) { - for (RecordProcessor<RecordType> processor : processors) { - try { - processor.process(record); - } catch (Exception e) { - throw new RecordProcessingException("Error processing record.", e); - } - } - } - - /** - * Activate the <code>endJob</code> methods of the - * registered processors. - * @param The LoopEvent which activated finish. - */ - public void finish(LoopEvent loopEvent) { - for (RecordProcessor<RecordType> processor : processors) { + @Override + public void finish(final LoopEvent loopEvent) { + for (final RecordProcessor<RecordType> processor : this.processors) { processor.endJob(); } } /** - * Activate the <code>startJob</code> methods of the - * registered processors. - * @param The LoopEvent which activated the start. + * Activate the <code>process</code> methods of the registered processors. + * + * @param record the current record */ - public void start(LoopEvent loopEvent) { - for (RecordProcessor<RecordType> processor : processors) { + public void process(final RecordType record) { + for (final RecordProcessor<RecordType> processor : this.processors) { + try { + processor.process(record); + } catch (final Exception e) { + throw new RecordProcessingException("Error processing record.", e); + } + } + } + + /** + * Remove a <code>RecordProcessor</code> from the adapter. + * + * @param processor the <code>RecordProcessor</code> to remove + */ + public void removeProcessor(final RecordProcessor<RecordType> processor) { + this.processors.remove(processor); + } + + /** + * Activate the <code>startJob</code> methods of the registered processors. + * + * @param the <code>LoopEvent</code> which activated the start + */ + @Override + public void start(final LoopEvent loopEvent) { + for (final RecordProcessor<RecordType> processor : this.processors) { processor.startJob(); } } - + /** - * Activate the <code>suspend</code> methods of the - * registered processors. - * @param The LoopEvent which activated the suspend. + * Activate the <code>startRun</code> methods of the registered processors. + * + * @param record the current record */ - public void suspend(LoopEvent loopEvent) { - for (RecordProcessor<RecordType> processor : processors) { + public void startRun(final RecordType record) { + for (final RecordProcessor<RecordType> processor : this.processors) { + processor.startRun(record); + } + } + + /** + * Activate the <code>suspend</code> methods of the registered processors. + * + * @param the <code>LoopEvent</code> which activated <code>suspend</code>. + */ + @Override + public void suspend(final LoopEvent loopEvent) { + for (final RecordProcessor<RecordType> processor : this.processors) { processor.suspend(); } - } + } } Added: java/trunk/record-util/src/main/java/org/hps/record/composite/package-info.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/composite/package-info.java (added) +++ java/trunk/record-util/src/main/java/org/hps/record/composite/package-info.java Mon Apr 13 17:23:55 2015 @@ -0,0 +1,7 @@ +/** + * This package implements a composite record processing system that creates and processes records which reference + * associated ET, EVIO and LCSim events. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ +package org.hps.record.composite; Modified: java/trunk/record-util/src/main/java/org/hps/record/enums/DataSourceType.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/enums/DataSourceType.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/enums/DataSourceType.java Mon Apr 13 17:23:55 2015 @@ -1,61 +1,36 @@ package org.hps.record.enums; - -import java.io.File; /** * The type of data source that will supply events to the app. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public enum DataSourceType { - ET_SERVER("ET Server", null), - EVIO_FILE("EVIO File", "evio"), + /** + * An ET server data source (hence no file extension). + */ + ET_SERVER("ET Server", null), + /** + * An EVIO data source with the "evio" file extension. + */ + EVIO_FILE("EVIO File", "evio"), + /** + * An LCIO data source with the "slcio" file extension. + */ LCIO_FILE("LCIO File", "slcio"); - String description; - String extension; - - /** - * Constructor which takes a description. - * @param description The description of the data source type. - */ - private DataSourceType(String description, String extension) { - this.description = description; - } - - /** - * Get the description of the data source type. - * @return The description of the data source type. - */ - public String description() { - return description; - } - - /** - * Get the extension associated with this data source type. - * @return The file extension of the data source type. - */ - public String getExtension() { - return extension; - } - - /** - * True if the source is file-based - * (e.g. not an ET server). - * @return - */ - public boolean isFile() { - return this.ordinal() > ET_SERVER.ordinal(); - } - /** * Figure out a reasonable data source type for the path string. - * This defaults to an ET source ((perhaps unreasonably!) if the - * file extension is unrecognized. + * <p> + * This defaults to an ET source ((perhaps unreasonably!) if the file extension is unrecognized. + * * @param path The data source path. * @return The data source type. */ - public static DataSourceType getDataSourceType(String path) { - if (path.endsWith("." + DataSourceType.LCIO_FILE.getExtension())) { + // FIXME: Probably this should throw an error if the extension is unrecognized. + public static DataSourceType getDataSourceType(final String path) { + if (path.endsWith("." + DataSourceType.LCIO_FILE.getExtension())) { return DataSourceType.LCIO_FILE; } else if (path.contains("." + DataSourceType.EVIO_FILE.getExtension())) { // For EVIO files, only check that the extension appears someplace in the name @@ -65,5 +40,51 @@ return DataSourceType.ET_SERVER; } } - + + /** + * The description of the data source. + */ + private String description; + + /** + * The extension associated with the type. + */ + private String extension; + + /** + * Class constructor, which takes a description and file extension. + * + * @param description the description of the data source type + * @param extension the associated file extension + */ + private DataSourceType(final String description, final String extension) { + this.description = description; + } + + /** + * Get the description of the data source type. + * + * @return the description of the data source type + */ + public String description() { + return this.description; + } + + /** + * Get the extension associated with this data source type. + * + * @return the file extension of the data source type + */ + public String getExtension() { + return this.extension; + } + + /** + * Return <code>true</code> if the source is file-based (e.g. not an ET server). + * + * @return <code>true</code> if the source is file-based + */ + public boolean isFile() { + return this.ordinal() > ET_SERVER.ordinal(); + } } Modified: java/trunk/record-util/src/main/java/org/hps/record/enums/ProcessingStage.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/enums/ProcessingStage.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/enums/ProcessingStage.java Mon Apr 13 17:23:55 2015 @@ -1,16 +1,25 @@ package org.hps.record.enums; /** -* When set this can be used to limit the number -* of processing stages that are excecuted by the -* {@link org.hps.record.composite.CompositeLoop}. -* For example, if the <code>ProcessingStage</code> -* is set to <code>EVIO</code> then the <code>ET</code> -* and <code>EVIO</code> adapters will be activated -* but LCIO events will not be created or processed. -*/ + * When set this can be used to limit the number of processing stages that are executed by the + * {@link org.hps.record.composite.CompositeLoop}. + * <p> + * For example, if the <code>ProcessingStage</code> is set to <code>EVIO</code> then the <code>ET</code> and + * <code>EVIO</code> adapters will be activated but LCIO events will not be created or processed. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ public enum ProcessingStage { + /** + * Execute only the reading of ET events from the server. + */ ET, + /** + * Execute reading of ET events and conversion to EVIO. + */ EVIO, + /** + * Execute full processing chain of ET to EVIO to LCIO. + */ LCIO } Added: java/trunk/record-util/src/main/java/org/hps/record/enums/package-info.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/enums/package-info.java (added) +++ java/trunk/record-util/src/main/java/org/hps/record/enums/package-info.java Mon Apr 13 17:23:55 2015 @@ -0,0 +1,6 @@ +/** + * Enums for the record-util module. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ +package org.hps.record.enums; Modified: java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEtProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEtProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEtProcessor.java Mon Apr 13 17:23:55 2015 @@ -10,25 +10,34 @@ /** * An ET event processor that builds EPICS events. - * - * @author Jeremy McCormick <[log in to unmask]> + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ +// FIXME: Class is currently unused. public class EpicsEtProcessor extends EtEventProcessor { - - EpicsEvioProcessor evioProcessor = new EpicsEvioProcessor(); - - public void process(EtEvent event) { + + /** + * The processor for creating the EPICS data class from EVIO data. + */ + private final EpicsEvioProcessor evioProcessor = new EpicsEvioProcessor(); + + /** + * Process an <code>EtEvent</code> and create an EPICS data object from it. + * + * @param event the <code>EtEvent</code> to process + */ + @Override + public void process(final EtEvent event) { EvioEvent evio; try { evio = new EvioReader(event.getDataBuffer()).parseNextEvent(); } catch (IOException | EvioException e) { throw new RuntimeException(e); - } - evioProcessor.process(evio); - if (evioProcessor.getEpicsScalarData() != null) { + } + this.evioProcessor.process(evio); + if (this.evioProcessor.getEpicsScalarData() != null) { System.out.println("EpicsEtProcessor created EpicsScalarData ..."); - System.out.println(evioProcessor.getEpicsScalarData()); + System.out.println(this.evioProcessor.getEpicsScalarData()); } } -} - +} Modified: java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEvioProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEvioProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEvioProcessor.java Mon Apr 13 17:23:55 2015 @@ -6,17 +6,35 @@ import org.jlab.coda.jevio.EvioEvent; /** - * This is an EVIO event processor that will read EPICS events (event tag 31) - * and turn them into {@link EpicsScalarData} objects. - * - * @author Jeremy McCormick <[log in to unmask]> + * This is an EVIO event processor that will read EPICS events (event tag 31) and turn them into {@link EpicsScalarData} + * objects. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public final class EpicsEvioProcessor extends EvioEventProcessor { - EpicsScalarData data; - - public void process(EvioEvent evio) { - + /** + * The current EPICS data object. + */ + private EpicsScalarData data; + + /** + * Get the current {@link EpicsScalarData} object created from record processing. + * + * @return the {@link EpicsScalarData} object created from record processing + */ + public EpicsScalarData getEpicsScalarData() { + return this.data; + } + + /** + * Process EVIO data and create a {@link EpicsScalarData} if EPICS data bank exists in the event. + * + * @param evio the <code>EvioEvent</code> that possibly has EPICS data + */ + @Override + public void process(final EvioEvent evio) { + if (evio.getHeader().getTag() != EvioEventConstants.EPICS_EVENT_TAG) { // Just silently skip these events because otherwise too many error messages might print. return; @@ -24,8 +42,8 @@ // Find the bank with the EPICS information. BaseStructure epicsBank = null; - BaseStructure topBank = evio.getChildrenList().get(0); - for (BaseStructure childBank : topBank.getChildrenList()) { + final BaseStructure topBank = evio.getChildrenList().get(0); + for (final BaseStructure childBank : topBank.getChildrenList()) { if (childBank.getHeader().getTag() == EvioEventConstants.EPICS_BANK_TAG) { epicsBank = childBank; break; @@ -33,16 +51,9 @@ } if (epicsBank != null) { - String epicsData = epicsBank.getStringData()[0]; - data = new EpicsScalarData(); - data.fromString(epicsData); - - //System.out.println("found EVIO data bank ..."); - //System.out.println(data.toString()); - } - } - - public EpicsScalarData getEpicsScalarData() { - return data; + final String epicsData = epicsBank.getStringData()[0]; + this.data = new EpicsScalarData(); + this.data.fromString(epicsData); + } } } Modified: java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsGenericObject.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsGenericObject.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsGenericObject.java Mon Apr 13 17:23:55 2015 @@ -3,21 +3,71 @@ import org.lcsim.event.GenericObject; /** - * This is an implementation of GenericObject for reading and writing EPICS data. - * There is no functionality here. Users that need this data in their <code>Driver</code> - * classes should instead use {@link EpicsScalarData#read(org.lcsim.event.EventHeader)} - * to create the class with the actual API. - * - * @author Jeremy McCormick <[log in to unmask]> + * This is an implementation of GenericObject for reading and writing EPICS data. There is no functionality here + * intended for ends users. Instead, the EPICS data should be accessed using + * {@link EpicsScalarData#read(org.lcsim.event.EventHeader)} to create the data object from input event data. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ final class EpicsGenericObject implements GenericObject { - String[] keys; - double[] values; + /** + * The names of the EPICS variables. + */ + private String[] keys; + + /** + * The values of the EPICS variables. + */ + private double[] values; + + /** + * Get a double value of an EPICS variable. + * + * @param index the index of the variable + */ + @Override + public double getDoubleVal(final int index) { + return this.values[index]; + } @Override - public int getNInt() { + public float getFloatVal(final int index) { return 0; + } + + @Override + public int getIntVal(final int index) { + return 0; + } + + /** + * Get a key by index. + * + * @param index the index + * @return the key which is the name of an EPICS variable + */ + public String getKey(final int index) { + return this.keys[index]; + } + + /** + * Get the keys which are the EPICS variable names. + * + * @return the keys + */ + String[] getKeys() { + return this.keys; + } + + /** + * Get the number of doubles which matches the number of EPICS variables. + * + * @return the number of double values + */ + @Override + public int getNDouble() { + return this.values.length; } @Override @@ -26,31 +76,53 @@ } @Override - public int getNDouble() { - return values.length; - } - - @Override - public int getIntVal(int index) { + public int getNInt() { return 0; } - @Override - public float getFloatVal(int index) { - return 0; - } - - @Override - public double getDoubleVal(int index) { - return values[index]; - } - + /** + * Returns <code>false</code> to indicate this object does not have a fixed size. + */ @Override public boolean isFixedSize() { return false; } - public String getKey(int index) { - return keys[index]; + /** + * Set a key string by index. + * + * @param index the index + * @param key the key string which is an EPICS variable + */ + void setKey(final int index, final String key) { + this.keys[index] = key; + } + + /** + * Set the keys. + * + * @param keys the keys array + */ + void setKeys(final String[] keys) { + this.keys = keys; + } + + /** + * Set a value by index. + * + * @param index the index + * @param value the value + */ + void setValue(final int index, final double value) { + this.values[index] = value; + } + + /** + * Set the values array. + * + * @param values the values array + */ + void setValues(final double[] values) { + this.values = values; } } Modified: java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsScalarData.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsScalarData.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsScalarData.java Mon Apr 13 17:23:55 2015 @@ -12,218 +12,242 @@ import org.lcsim.event.GenericObject; /** - * This is an API for reading and writing EPICS scalar data to LCIO events, - * as well as parsing the scalar data from a CDATA section of an EVIO string - * data bank. The {@link #read(EventHeader)} method should be used to create - * one of these objects from an LCIO event. - * - * @author Jeremy McCormick <[log in to unmask]> -*/ + * This is an API for reading and writing EPICS scalar data to LCIO events, as well as parsing the scalar data from a + * CDATA section within an EVIO string data bank. The {@link #read(EventHeader)} method should be used to create one of + * these objects from an LCIO event. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ public final class EpicsScalarData { - - // Used in collection parameter map as name of the key list. + + /** + * Default collection name in the LCSim events. + */ + public static final String DEFAULT_COLLECTION_NAME = "EpicsScalarData"; + + /** + * This map contains the list of EPICS key descriptions from the<br/> + * <a href="https://confluence.slac.stanford.edu/display/hpsg/EVIO+Data+Format">EVIO Data Format Confluence Page</a> + */ + private final static Map<String, String> DESCRIPTIONS = new HashMap<String, String>(); + + /** + * Dummy float parameters to make LCIO persistency work. + */ + static final Map<String, float[]> DUMMY_FLOAT_MAP = new HashMap<String, float[]>(); + + /** + * Dummy int parameters to make LCIO persistency work. + */ + static final Map<String, int[]> DUMMY_INT_MAP = new HashMap<String, int[]>(); + + /** + * Collection parameter that has the EPICS variable names. + */ public static final String EPICS_SCALAR_NAMES = "EPICS_SCALAR_NAMES"; - - // Default collection name in the LCIO event. - public static final String DEFAULT_COLLECTION_NAME = "EpicsScalarData"; - - // Dummy collection parameter maps to try and make LCIO happy. - static final Map<String, int[]> DUMMY_INT_MAP = new HashMap<String, int[]>(); - static final Map<String, float[]> DUMMY_FLOAT_MAP = new HashMap<String, float[]>(); - - // The map of scalar keys to values. - private Map<String, Double> dataMap = new LinkedHashMap<String, Double>(); - - // EPICS key descriptions from - // https://confluence.slac.stanford.edu/display/hpsg/EVIO+Data+Format - private final static Map<String, String> DESCRIPTIONS = new HashMap<String, String>(); + + /** + * List of descriptions. + */ + // FIXME: Maybe this should not be listed here. static { - DESCRIPTIONS.put("MBSY2C_energy", "Beam energy according to Hall B BSY dipole string"); - DESCRIPTIONS.put("PSPECIRBCK", "Pair Spectrometer Current Readback"); - DESCRIPTIONS.put("HPS:LS450_2:FIELD", "Frascati probe field"); - DESCRIPTIONS.put("HPS:LS450_1:FIELD", "Pair Spectrometer probe field"); - DESCRIPTIONS.put("MTIRBCK", "Frascati Current Readback"); - DESCRIPTIONS.put("VCG2C21 2C21", "Vacuum gauge pressure"); - DESCRIPTIONS.put("VCG2C21A", "2C21A Vacuum gauge pressure"); - DESCRIPTIONS.put("VCG2C24A", "2C24A Vacuum gauge pressure"); - DESCRIPTIONS.put("VCG2H00A", "2H00 Vacuum gauge pressure"); - DESCRIPTIONS.put("VCG2H01A", "2H01 Vacuum gauge pressure"); - DESCRIPTIONS.put("VCG2H02A", "2H02 Vacuum gauge pressure"); - DESCRIPTIONS.put("scaler_calc1", "Faraday cup current"); - DESCRIPTIONS.put("scalerS12b", "HPS-Left beam halo count"); - DESCRIPTIONS.put("scalerS13b", "HPS-Right beam halo count"); - DESCRIPTIONS.put("scalerS14b", "HPS-Top beam halo count"); - DESCRIPTIONS.put("scalerS15b", "HPS-SC beam halo count"); + DESCRIPTIONS.put("MBSY2C_energy", "Beam energy according to Hall B BSY dipole string"); + DESCRIPTIONS.put("PSPECIRBCK", "Pair Spectrometer Current Readback"); + DESCRIPTIONS.put("HPS:LS450_2:FIELD", "Frascati probe field"); + DESCRIPTIONS.put("HPS:LS450_1:FIELD", "Pair Spectrometer probe field"); + DESCRIPTIONS.put("MTIRBCK", "Frascati Current Readback"); + DESCRIPTIONS.put("VCG2C21 2C21", "Vacuum gauge pressure"); + DESCRIPTIONS.put("VCG2C21A", "2C21A Vacuum gauge pressure"); + DESCRIPTIONS.put("VCG2C24A", "2C24A Vacuum gauge pressure"); + DESCRIPTIONS.put("VCG2H00A", "2H00 Vacuum gauge pressure"); + DESCRIPTIONS.put("VCG2H01A", "2H01 Vacuum gauge pressure"); + DESCRIPTIONS.put("VCG2H02A", "2H02 Vacuum gauge pressure"); + DESCRIPTIONS.put("scaler_calc1", "Faraday cup current"); + DESCRIPTIONS.put("scalerS12b", "HPS-Left beam halo count"); + DESCRIPTIONS.put("scalerS13b", "HPS-Right beam halo count"); + DESCRIPTIONS.put("scalerS14b", "HPS-Top beam halo count"); + DESCRIPTIONS.put("scalerS15b", "HPS-SC beam halo count"); DESCRIPTIONS.put("hallb_IPM2C21A_XPOS", "Beam position X at 2C21"); DESCRIPTIONS.put("hallb_IPM2C21A_YPOS", "Beam position Y at 2C21"); - DESCRIPTIONS.put("hallb_IPM2C21A_CUR", "Current at 2C21"); + DESCRIPTIONS.put("hallb_IPM2C21A_CUR", "Current at 2C21"); DESCRIPTIONS.put("hallb_IPM2C24A_XPOS", "Beam position X at 2C24"); DESCRIPTIONS.put("hallb_IPM2C24A_YPOS", "Beam position Y at 2C24"); - DESCRIPTIONS.put("hallb_IPM2C24A_CUR", "Current at 2C24"); - DESCRIPTIONS.put("hallb_IPM2H00_XPOS", "Beam position X at 2H00"); - DESCRIPTIONS.put("hallb_IPM2H00_YPOS", "Beam position Y at 2H00"); - DESCRIPTIONS.put("hallb_IPM2H00_CUR", "Current at 2H00"); - DESCRIPTIONS.put("hallb_IPM2H02_YPOS", "Beam position X at 2H02"); - DESCRIPTIONS.put("hallb_IPM2H02_XPOS", "Beam position Y at 2H02"); + DESCRIPTIONS.put("hallb_IPM2C24A_CUR", "Current at 2C24"); + DESCRIPTIONS.put("hallb_IPM2H00_XPOS", "Beam position X at 2H00"); + DESCRIPTIONS.put("hallb_IPM2H00_YPOS", "Beam position Y at 2H00"); + DESCRIPTIONS.put("hallb_IPM2H00_CUR", "Current at 2H00"); + DESCRIPTIONS.put("hallb_IPM2H02_YPOS", "Beam position X at 2H02"); + DESCRIPTIONS.put("hallb_IPM2H02_XPOS", "Beam position Y at 2H02"); + } + + /** + * Get the static list of available EPICs scalar names. + * <p> + * This could be different than the variable names which were actually written into the collection header. For this, + * instead use the method {@link #getUsedNames()}. + * + * @return the set of default EPICS scalar names + */ + public static Set<String> getDefaultNames() { + return DESCRIPTIONS.keySet(); }; - - /** - * Write this object's data into a GenericObject collection in the LCIO event using - * the default collection name. - * @param event The LCIO event. - */ - public void write(EventHeader event) { - write(event, DEFAULT_COLLECTION_NAME); - } - + + /** + * Get the description of a named EPICS variable. + * + * @param name the name of the scalar + */ + public static String getDescription(final String name) { + return DESCRIPTIONS.get(name); + } + /** * <p> * Read data into this object from an LCIO event using the default collection name. * <p> - * This is the primary method for users to read the EPICS data into their Drivers - * in the {@link org.lcsim.util.Driver#process(EventHeader)} method. - * @param event The LCIO event. - * @return The EPICS data from the event. - */ - public static EpicsScalarData read(EventHeader event) { + * This is the primary method for users to read the EPICS data into their Drivers in the + * {@link org.lcsim.util.Driver#process(EventHeader)} method. + * + * @param event the LCIO event + * @return the EPICS data from the event + */ + public static EpicsScalarData read(final EventHeader event) { if (event.hasCollection(GenericObject.class, EpicsScalarData.DEFAULT_COLLECTION_NAME)) { return read(event, DEFAULT_COLLECTION_NAME); } else { return null; } } - - /** - * Get a double value from the key. - * @return The value from the key. - */ - public Double getValue(String name) { - return dataMap.get(name); - } - - /** - * Get the description of a named EPICS scalar. - * @param name The name of the scalar. - */ - public static String getDescription(String name) { - return DESCRIPTIONS.get(name); - } - - /** - * Get the static list of default, available EPICs scalar names. - * <p> - * This could be different than the names which were actually - * written into the collection header. For this, use the method - * {@link #getUsedNames()}. - * - * @return The list of default EPICS scalar names. - */ - public static Set<String> getDefaultNames() { - return DESCRIPTIONS.keySet(); - } - - /** - * Get the list of used EPICS scalars in this object. - * <p> - * This could potentially be different than the list of - * default names from {@link #getDefaultNames()} but it - * will usually be the same. - * - * @return The list of used EPICS scalar names. - */ - public Set<String> getUsedNames() { - return dataMap.keySet(); - } - - /** - * Write this object into an LCIO event under the given collection name. - * @param event The LCIO event. - * @param collectionName The name of the collection in the event. - */ - void write(EventHeader event, String collectionName) { - List<GenericObject> collection = new ArrayList<GenericObject>(); - EpicsGenericObject object = toGenericObject(); - collection.add(object); - Map<String, String[]> stringMap = new HashMap<String, String[]>(); - stringMap.put(EPICS_SCALAR_NAMES, object.keys); - event.put(collectionName, collection, GenericObject.class, 0, DUMMY_INT_MAP, DUMMY_FLOAT_MAP, stringMap); - } - - /** - * Parse a raw data string from the EVIO data bank and - * turn it into a list of keys and values within this object. - * @param rawData The raw data in the form of a string. - */ - void fromString(String rawData) { - String lines[] = rawData.split("\\r?\\n"); - for (String line : lines) { - String trimmed = line.trim(); + + /** + * Read data into this object from a collection in the LCIO event with the given collection name. + * + * @param event the LCIO event + * @param collectionName the collection name + * @return the EPICS data from the LCIO event + */ + static EpicsScalarData read(final EventHeader event, final String collectionName) { + final List<GenericObject> collection = event.get(GenericObject.class, collectionName); + @SuppressWarnings("rawtypes") + final Map stringMap = event.getMetaData(collection).getStringParameters(); + final String[] keys = (String[]) stringMap.get(EPICS_SCALAR_NAMES); + final EpicsScalarData data = new EpicsScalarData(); + data.fromGenericObject(collection.get(0), keys); + return data; + } + + /** + * The mapping of EPICS variable names to their double values. + */ + private final Map<String, Double> dataMap = new LinkedHashMap<String, Double>(); + + /** + * Given a list of names, read the double values from the {@link org.lcsim.event.GenericObject} into the data map of + * this object. + * + * @param object the <code>GenericObject</code> with the scalar values + * @param names The list of names. + */ + void fromGenericObject(final GenericObject object, final String[] names) { + for (int index = 0; index < names.length; index++) { + this.dataMap.put(names[index], object.getDoubleVal(index)); + } + } + + /** + * Parse a raw data string from the EVIO data bank and turn it into a list of keys and values within this object. + * + * @param rawData the raw EPICS data in the form of a string + */ + void fromString(final String rawData) { + final String lines[] = rawData.split("\\r?\\n"); + for (final String line : lines) { + final String trimmed = line.trim(); if (trimmed.length() == 0) { continue; } - String[] data = trimmed.split(" "); - Double value = Double.parseDouble(data[0]); - String key = data[1]; - dataMap.put(key, value); - } - } - - /** - * Convert this object into a {@link org.lcsim.event.GenericObject} - * that can be written into an LCIO collection. - * @return The GenericObject representing this data. + final String[] data = trimmed.split(" "); + final Double value = Double.parseDouble(data[0]); + final String key = data[1]; + this.dataMap.put(key, value); + } + } + + /** + * Get the list of used EPICS scalars in this object. + * <p> + * This could potentially be different than the list of default names from {@link #getDefaultNames()} but it will + * usually be the same. + * + * @return the list of used EPICS scalar names + */ + public Set<String> getUsedNames() { + return this.dataMap.keySet(); + } + + /** + * Get a double value from the key which should be a valid EPICS variable name. + * + * @return the value from the key + */ + public Double getValue(final String name) { + return this.dataMap.get(name); + } + + /** + * Convert this object into a {@link org.lcsim.event.GenericObject} that can be written into an LCIO collection. + * + * @return the <code>GenericObject</code> representing this data */ EpicsGenericObject toGenericObject() { - EpicsGenericObject newObject = new EpicsGenericObject(); - newObject.keys = new String[dataMap.size()]; - newObject.values = new double[dataMap.size()]; + final EpicsGenericObject newObject = new EpicsGenericObject(); + newObject.setKeys(new String[this.dataMap.size()]); + newObject.setValues(new double[this.dataMap.size()]); int index = 0; - for (String key : dataMap.keySet()) { - newObject.keys[index] = key; - newObject.values[index] = dataMap.get(key); + for (final String key : this.dataMap.keySet()) { + newObject.setKey(index, key); + newObject.setValue(index, this.dataMap.get(key)); index++; } return newObject; } /** - * Given a list of names, read the double values from the - * {@link org.lcsim.event.GenericObject} into the data map - * of this object. - * @param object The GenericObject with the scalar values. - * @param names The list of names. - */ - void fromGenericObject(GenericObject object, String[] names) { - for (int index = 0; index < names.length; index++) { - dataMap.put(names[index], object.getDoubleVal(index)); - } - } - - /** - * Read data into this object from a collection in the LCIO event - * with the given collection name. - * @param event The LCIO event. - * @param collectionName The collection name. - * @return The EPICS data from the LCIO event. - */ - static EpicsScalarData read(EventHeader event, String collectionName) { - List<GenericObject> collection = event.get(GenericObject.class, collectionName); - @SuppressWarnings("rawtypes") - Map stringMap = event.getMetaData(collection).getStringParameters(); - String[] keys = (String[]) stringMap.get(EPICS_SCALAR_NAMES); - EpicsScalarData data = new EpicsScalarData(); - data.fromGenericObject(collection.get(0), keys); - return data; - } - - /** * Convert this object to a string. - */ + * + * @return this object converted to a string + */ + @Override public String toString() { - StringBuffer sb = new StringBuffer(); - for (Entry<String, Double> entry : dataMap.entrySet()) { + final StringBuffer sb = new StringBuffer(); + for (final Entry<String, Double> entry : this.dataMap.entrySet()) { sb.append(entry.getKey() + " " + entry.getValue() + '\n'); } return sb.toString(); } + + /** + * Write this object's data into a <code>GenericObject</code> collection in the LCIO event using the default + * collection name. + * + * @param event the LCIO event + */ + public void write(final EventHeader event) { + write(event, DEFAULT_COLLECTION_NAME); + } + + /** + * Write this object into an LCIO event with the given collection name. + * + * @param event the LCIO event + * @param collectionName the name of the collection in the output event + */ + void write(final EventHeader event, final String collectionName) { + final List<GenericObject> collection = new ArrayList<GenericObject>(); + final EpicsGenericObject object = toGenericObject(); + collection.add(object); + final Map<String, String[]> stringMap = new HashMap<String, String[]>(); + stringMap.put(EPICS_SCALAR_NAMES, object.getKeys()); + event.put(collectionName, collection, GenericObject.class, 0, DUMMY_INT_MAP, DUMMY_FLOAT_MAP, stringMap); + } } Added: java/trunk/record-util/src/main/java/org/hps/record/epics/package-info.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/epics/package-info.java (added) +++ java/trunk/record-util/src/main/java/org/hps/record/epics/package-info.java Mon Apr 13 17:23:55 2015 @@ -0,0 +1,6 @@ +/** + * Classes for reading EPICs data from EVIO and converting it to LCSim. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ +package org.hps.record.epics; Modified: java/trunk/record-util/src/main/java/org/hps/record/et/EtConnection.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/et/EtConnection.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/et/EtConnection.java Mon Apr 13 17:23:55 2015 @@ -22,153 +22,44 @@ import org.jlab.coda.et.exception.EtWakeUpException; /** - * A class for encapsulating the connection information - * for an ET client including the EtSystem and EtAttachment + * A class for encapsulating the connection information for an ET client including the EtSystem and EtAttachment * objects. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public final class EtConnection { - EtSystem sys; - EtAttachment att; - EtStation stat; - - Mode waitMode; - int waitTime; - int chunkSize; - - /** - * A class constructor for internal convenience. - * @param param The connection parameters. - * @param sys The ET system. - * @param att The ET attachment. - * @param stat The ET station. - */ - private EtConnection( - EtSystem sys, - EtAttachment att, - EtStation stat, - Mode waitMode, - int waitTime, - int chunkSize) { - this.sys = sys; - this.att = att; - this.stat = stat; - this.waitMode = waitMode; - this.waitTime = waitTime; - this.chunkSize = chunkSize; - } - - /** - * Get the ET system. - * @return The ET system. - */ - public EtSystem getEtSystem() { - return sys; - } - - /** - * Get the ET attachment. - * @return The ET attachment. - */ - public EtAttachment getEtAttachment() { - return att; - } - - /** - * Get the ET station. - * @return The ET station. - */ - public EtStation getEtStation() { - return stat; - } - - /** - * Cleanup the ET connection. - */ - public void cleanup() { + /** + * Create an EtConnection with full list of configuration parameters. + * + * @param name the name of the ET system e.g. the buffer file on disk + * @param host the name of the network host + * @param port the port of the network host + * @param blocking <code>true</code> for blocking behavior + * @param queueSize the queue size + * @param prescale the event prescale factor or 0 for none + * @param stationName the name of the ET station + * @param stationPosition he position of the ET station + * @param waitMode the wait mode + * @param waitTime the wait time if using timed wait mode + * @param chunkSize the number of ET events to return at once + * @return the <code>EtConnection</code> created from the parameters + */ + public static EtConnection createConnection(final String name, final String host, final int port, + final boolean blocking, final int queueSize, final int prescale, final String stationName, + final int stationPosition, final Mode waitMode, final int waitTime, final int chunkSize) { try { - if (!sys.alive()) { - throw new RuntimeException("EtSystem is not alive!"); - } - sys.detach(att); - sys.removeStation(stat); - sys.close(); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Read EtEvent objects from the ET server. - * - * Preserve all specific Exception types in the throws clause so caller - * may implement their own error and state handling. - * - * @return The array of EtEvents. - * @throws IOException - * @throws EtException - * @throws EtDeadException - * @throws EtEmptyException - * @throws EtBusyException - * @throws EtTimeoutException - * @throws EtWakeUpException - * @throws EtClosedException - */ - EtEvent[] readEtEvents() - throws IOException, EtException, EtDeadException, - EtEmptyException, EtBusyException, EtTimeoutException, - EtWakeUpException, EtClosedException { - return getEtSystem().getEvents( - getEtAttachment(), - waitMode, - Modify.NOTHING, - waitTime, - chunkSize); - } - - /** - * Create an EtConnection with full list of configuration parameters. - * @param name The name of the ET system e.g. the buffer file on disk. - * @param host The name of the network host. - * @param port The port of the network host. - * @param blocking True for blocking behavior. - * @param queueSize The queue size. - * @param prescale The event prescale or 0 for none. - * @param stationName The name of the ET station. - * @param stationPosition The position of the ET station. - * @param waitMode The wait mode. - * @param waitTime The wait time if using timed wait. - * @param chunkSize The number of ET events to return at once. - * @return The EtConnection created from the parameters. - */ - public static EtConnection createConnection( - String name, - String host, - int port, - boolean blocking, - int queueSize, - int prescale, - String stationName, - int stationPosition, - Mode waitMode, - int waitTime, - int chunkSize) { - try { - - // make a direct connection to ET system's tcp server - EtSystemOpenConfig etConfig = new EtSystemOpenConfig( - name, - host, - port); + + // make a direct connection to ET system's tcp server + final EtSystemOpenConfig etConfig = new EtSystemOpenConfig(name, host, port); // create ET system object with verbose debugging output - EtSystem sys = new EtSystem(etConfig, EtConstants.debugInfo); + final EtSystem sys = new EtSystem(etConfig, EtConstants.debugInfo); sys.open(); // configuration of a new station - EtStationConfig stationConfig = new EtStationConfig(); - //statConfig.setFlowMode(cn.flowMode); + final EtStationConfig stationConfig = new EtStationConfig(); + // statConfig.setFlowMode(cn.flowMode); // FIXME: Flow mode hard-coded. stationConfig.setFlowMode(EtConstants.stationSerial); if (!blocking) { @@ -179,58 +70,146 @@ } // Set prescale. if (prescale > 0) { - //System.out.println("setting prescale to " + cn.prescale); + // System.out.println("setting prescale to " + cn.prescale); stationConfig.setPrescale(prescale); } // Create the station. - EtStation stat = sys.createStation( - stationConfig, - stationName, - stationPosition); + final EtStation stat = sys.createStation(stationConfig, stationName, stationPosition); // attach to new station - EtAttachment att = sys.attach(stat); + final EtAttachment att = sys.attach(stat); // Return new connection. - EtConnection connection = new EtConnection( - sys, - att, - stat, - waitMode, - waitTime, - chunkSize - ); - + final EtConnection connection = new EtConnection(sys, att, stat, waitMode, waitTime, chunkSize); + return connection; - } catch (IOException | - EtException | - EtExistsException | - EtClosedException | - EtDeadException | - EtTooManyException e) { + } catch (IOException | EtException | EtExistsException | EtClosedException | EtDeadException + | EtTooManyException e) { throw new RuntimeException("Failed to create ET connection.", e); } } - - /** - * Create an EtConnection with a set of default parameters. - * @return An EtConnection with default parameters. + + /** + * Create an <code>EtConnection</code> with a set of default parameters. + * + * @return an <code>EtConnection</code> with default parameters */ public static EtConnection createDefaultConnection() { - return createConnection( - "ETBuffer", - "localhost", - 11111, - false, - 0, - 0, - "MY_STATION", - 1, - Mode.TIMED, - 5000000, - 1); - } - + return createConnection("ETBuffer", "localhost", 11111, false, 0, 0, "MY_STATION", 1, Mode.TIMED, 5000000, 1); + } + + /** + * The ET attachment. + */ + private final EtAttachment att; + + /** + * The chunk size. + */ + private final int chunkSize; + + /** + * The ET station. + */ + private final EtStation stat; + + /** + * The ET system object representing the connection to the server. + */ + private final EtSystem sys; + + /** + * The wait mode. + */ + private final Mode waitMode; + + /** + * The wait time. + */ + private final int waitTime; + + /** + * A class constructor for internal convenience. + * + * @param param The connection parameters. + * @param sys The ET system. + * @param att The ET attachment. + * @param stat The ET station. + */ + private EtConnection(final EtSystem sys, final EtAttachment att, final EtStation stat, final Mode waitMode, + final int waitTime, final int chunkSize) { + this.sys = sys; + this.att = att; + this.stat = stat; + this.waitMode = waitMode; + this.waitTime = waitTime; + this.chunkSize = chunkSize; + } + + /** + * Cleanup the ET connection. + */ + public void cleanup() { + try { + if (!this.sys.alive()) { + throw new RuntimeException("EtSystem is not alive!"); + } + this.sys.detach(this.att); + this.sys.removeStation(this.stat); + this.sys.close(); + } catch (final Exception e) { + e.printStackTrace(); + } + } + + /** + * Get the ET attachment. + * + * @return The ET attachment. + */ + public EtAttachment getEtAttachment() { + return this.att; + } + + /** + * Get the ET station. + * + * @return The ET station. + */ + public EtStation getEtStation() { + return this.stat; + } + + /** + * Get the ET system. + * + * @return The ET system. + */ + public EtSystem getEtSystem() { + return this.sys; + } + + /** + * Read an array of <code>EtEvent</code> objects from the ET server. + * <p> + * Method signature preserves all specific exception types in the throws clause so that the caller may easily + * implement their own error and state handling depending on the kind of error that was thrown. + * + * @return The array of EtEvents. + * @throws IOException if <code>getEvents</code> throws this exception type + * @throws EtException if <code>getEvents</code> throws this exception type + * @throws EtDeadException if <code>getEvents</code> throws this exception type + * @throws EtEmptyException if <code>getEvents</code> throws this exception type + * @throws EtBusyException if <code>getEvents</code> throws this exception type + * @throws EtTimeoutException if <code>getEvents</code> throws this exception type + * @throws EtWakeUpException if <code>getEvents</code> throws this exception type + * @throws EtClosedException if <code>getEvents</code> throws this exception type + */ + EtEvent[] readEtEvents() throws IOException, EtException, EtDeadException, EtEmptyException, EtBusyException, + EtTimeoutException, EtWakeUpException, EtClosedException { + return getEtSystem().getEvents(getEtAttachment(), this.waitMode, Modify.NOTHING, this.waitTime, this.chunkSize); + } + } Modified: java/trunk/record-util/src/main/java/org/hps/record/et/EtEventProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/et/EtEventProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/et/EtEventProcessor.java Mon Apr 13 17:23:55 2015 @@ -4,8 +4,9 @@ import org.jlab.coda.et.EtEvent; /** - * This is the basic abstract class that processors of - * <tt>EtEvent</tt> objects should extend. + * This is the basic abstract class that processors of <tt>EtEvent</tt> objects should extend. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public abstract class EtEventProcessor extends AbstractRecordProcessor<EtEvent> { } Modified: java/trunk/record-util/src/main/java/org/hps/record/et/EtEventQueue.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/et/EtEventQueue.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/et/EtEventQueue.java Mon Apr 13 17:23:55 2015 @@ -5,15 +5,19 @@ /** * A dynamic queue for supplying <tt>EtEvent</tt> objects to a loop. - * This would most likely be run on a separate thread than the - * loop to avoid undesired blocking behavior. + * <p> + * This should be run on a separate thread than the loop to avoid undesired blocking behavior. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ +// FIXME: This class is unused within HPS Java. public final class EtEventQueue extends AbstractRecordQueue<EtEvent> { - /** - * Get the class of the record that is supplied. - * @return The class of the supplied records. - */ + /** + * Get the class of the record that is supplied. + * + * @return the class of the supplied records + */ @Override public Class<EtEvent> getRecordClass() { return EtEvent.class; Modified: java/trunk/record-util/src/main/java/org/hps/record/et/EtEventSource.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/et/EtEventSource.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/et/EtEventSource.java Mon Apr 13 17:23:55 2015 @@ -10,103 +10,128 @@ import org.jlab.coda.et.EtEvent; /** - * Implement a loop record source supplying <tt>EtEvent</tt> objects - * from an ET server connection. + * Implementation of a record source supplying <tt>EtEvent</tt> objects from an ET server connection to a record loop. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public final class EtEventSource extends AbstractRecordSource { - - EtConnection connection; - EtEvent currentRecord; - Queue<EtEvent> eventQueue = new LinkedBlockingQueue<EtEvent>(); - + + /** + * Indicates ET system error occurred. + */ + @SuppressWarnings("serial") + public static class EtSourceException extends IOException { + + /** + * Class constructor. + * + * @param message the error message + * @param cause the cause of the error + */ + public EtSourceException(final String message, final Exception cause) { + super(message, cause); + } + } + + /** + * The ET connection information. + */ + private final EtConnection connection; + + /** + * The current ET record. + */ + private EtEvent currentRecord; + + /** + * The ET event queue. + */ + private final Queue<EtEvent> eventQueue = new LinkedBlockingQueue<EtEvent>(); + /** * Constructor that requires the connection parameters. - * @param connection The EtConnection that should have a valid set of ET - * connection parameters. + * + * @param connection the <code>EtConnection</code> which should have a valid set of ET connection parameters */ - public EtEventSource(EtConnection connection) { + public EtEventSource(final EtConnection connection) { this.connection = connection; } - + /** * Get the current record. - * @return The current record. + * + * @return the current record */ @Override public Object getCurrentRecord() throws IOException { - return currentRecord; + return this.currentRecord; } - + /** - * True because this source supports the <code>next</code> method. - * @return True because this source supports next. + * Return <code>true</code> if the current record is not <code>null</code> + * + * @return <code>true</code> if the current record is not <code>null</code> + */ + @Override + public boolean hasCurrent() { + return this.currentRecord != null; + } + + /** + * Load the next <code>EtEvent</code>. + * <p> + * A cached record will be read from the queue or more records will be fetched from the ET server if the queue is + * empty. + * + * @throws NoSuchRecordException if the queue is empty and getting more records from the ET server fails + */ + @Override + public void next() throws IOException, NoSuchRecordException { + + // Fill the queue if there are no events cached. + if (this.eventQueue.size() == 0) { + readEtEvents(); + } + + // Poll the queue. + this.currentRecord = this.eventQueue.poll(); + + if (this.currentRecord == null) { + throw new NoSuchRecordException("ET record queue is empty."); + } + } + + /** + * Read the next <code>EtEvent</code> array from the ET server. + * + * @throws IOException if reading the events fails + */ + private void readEtEvents() throws IOException { + try { + final EtEvent[] mevs = this.connection.readEtEvents(); + this.eventQueue.addAll(Arrays.asList(mevs)); + } catch (final Exception e) { + throw new EtSourceException("Error while reading ET events.", e); + } + } + + /** + * Get the number of records, which is the size of the current queue. + * + * @return the size of the queue + */ + @Override + public long size() { + return this.eventQueue.size(); + } + + /** + * Return <code>true</code> because this source supports the <code>next</code> method + * + * @return <code>true</code> because this source supports the <code>next</code> method */ @Override public boolean supportsNext() { return true; } - - /** - * True if the current record is non-null. - * @return True if current record is non-null. - */ - @Override - public boolean hasCurrent() { - return currentRecord != null; - } - - /** - * Load the next <code>EtEvent</code> which will either read - * a cached record from the queue or fetch more records from - * the ET server if the queue is empty. - * @throws NoSuchRecordException if the queue is empty and getting - * more records from the ET server fails. - */ - @Override - public void next() throws IOException, NoSuchRecordException { - - // Fill the queue if there are no events cached. - if (eventQueue.size() == 0) { - readEtEvents(); - } - - // Poll the queue. - currentRecord = eventQueue.poll(); - - if (currentRecord == null) { - throw new NoSuchRecordException("ET record queue is empty."); - } - } - - /** - * Get the number of records which is the size of the current queue. - * @return The size of the queue. - */ - @Override - public long size() { - return this.eventQueue.size(); - } - - /** - * Read the next <code>EtEvent</code> array from the ET server. - * @throws IOException if reading events fails. - */ - private void readEtEvents() throws IOException { - try { - EtEvent[] mevs = connection.readEtEvents(); - eventQueue.addAll(Arrays.asList(mevs)); - } catch (Exception e) { - throw new EtSourceException("Error while reading ET events.", e); - } - } - - /** - * An error that is used to indicate an error in the ET system - * for the error handling of the loop. - */ - public static class EtSourceException extends IOException { - public EtSourceException(String message, Exception cause) { - super(message, cause); - } - } } Modified: java/trunk/record-util/src/main/java/org/hps/record/et/EtStationThread.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/et/EtStationThread.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/et/EtStationThread.java Mon Apr 13 17:23:55 2015 @@ -22,39 +22,67 @@ /** * <p> - * This is a class which runs ET event processing on a separate thread - * using an ET station that is assigned to its own unique <code>EtSystem</code>. + * This is a class which runs ET event processing on a separate thread using an ET station that is assigned to its own + * unique <code>EtSystem</code>. * <p> * Specific processing of ET events is provided with an {@link EtEventProcessor}. - * - * @author Jeremy McCormick <[log in to unmask]> + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ +// FIXME: Currently this is unused in HPS Java. public final class EtStationThread extends Thread { - - EtEventProcessor processor; - int stationPosition; - String name; - - EtSystem system; - EtStation station; - EtAttachment attachment; - - int[] select; - + + /** + * The ET attachment. + */ + private EtAttachment attachment; + + /** + * The station name. + */ + private final String name; + + /** + * The ET event processor. + */ + private final EtEventProcessor processor; + + /** + * The station event selection array. + */ + private int[] select; + + /** + * The ET station. + */ + private EtStation station; + + /** + * The station position. + */ + private final int stationPosition; + + /** + * The <code>EtSystem</code> that represents the connection to the ET server. + */ + private EtSystem system; + /** * This creates an ET station that will run an ET processor on a separate thread. - * @param processor The ET processor. - * @param system The ET system. - * @param name The name of the station. - * @param stationPosition The station's position. - * @param select The station's select array (can be null). - */ - public EtStationThread(EtEventProcessor processor, EtSystem system, String name, int stationPosition, int[] select) { + * + * @param processor the ET processor + * @param system the ET system + * @param name the name of the station + * @param stationPosition the station's position + * @param select the station's select array (can be null) + */ + public EtStationThread(final EtEventProcessor processor, final EtSystem system, final String name, + final int stationPosition, final int[] select) { if (processor == null) { throw new IllegalArgumentException("processor is null"); } if (system == null) { - throw new IllegalArgumentException("system is null"); + throw new IllegalArgumentException("system is null"); } if (name == null) { throw new IllegalArgumentException("name is null"); @@ -68,132 +96,133 @@ } this.select = select; } - + this.processor = processor; this.name = name; - this.stationPosition = stationPosition; - + this.stationPosition = stationPosition; + // Copy parameters from the provided EtSystem. try { this.system = new EtSystem(new EtSystemOpenConfig(system.getConfig())); - } catch (EtException e) { + } catch (final EtException e) { throw new RuntimeException("Error setting up station.", e); } } - - /** - * Setup this station for receiving events. - */ - protected void setup() { - - if (!system.alive()) { - try { - system.open(); - } catch (IOException | EtException | EtTooManyException e) { - throw new RuntimeException("Failed to open ET system.", e); - } - } - - try { - // Create the basic station configuration. - EtStationConfig stationConfig = new EtStationConfig(); - stationConfig.setFlowMode(EtConstants.stationSerial); - stationConfig.setBlockMode(EtConstants.stationNonBlocking); - - // Setup event selection. - if (select != null) { - stationConfig.setSelect(select); - stationConfig.setSelectMode(EtConstants.stationSelectMatch); - } - - // Create station and attach to the ET system. - station = system.createStation(stationConfig, name, stationPosition); - attachment = system.attach(station); - - } catch (Exception e) { - // Any errors during setup are re-thrown. - throw new RuntimeException(e); - } - } - + + /** + * Disconnect the station. + * <p> + * This happens automatically at the end of the {@link #run()} method. + */ + synchronized final void disconnect() { + if (this.system.alive()) { + if (this.attachment.isUsable()) { + try { + this.system.detach(this.attachment); + } catch (IOException | EtException | EtClosedException | EtDeadException e) { + e.printStackTrace(); + } + } + this.system.close(); + } + } + /** * Run event processing on the station until woken up or interrupted. */ + @Override public final void run() { - - // Setup the ET system. + + // Setup the ET system before processing events. + // FIXME: Should be called outside this method? setup(); - + // Process ET events. try { - for (;;) { - + for (;;) { + EtEvent[] events; - - try { - events = system.getEvents(attachment, Mode.SLEEP, Modify.NOTHING, 0, 1 /* hard-coded to read 1 event for now */); - system.putEvents(attachment, events); - } catch (EtWakeUpException e) { + + try { + events = this.system.getEvents(this.attachment, Mode.SLEEP, Modify.NOTHING, 0, 1); + this.system.putEvents(this.attachment, events); + } catch (final EtWakeUpException e) { e.printStackTrace(); break; - } catch (EtException | EtDeadException | - EtClosedException | EtEmptyException | - EtBusyException | EtTimeoutException | - IOException e) { + } catch (EtException | EtDeadException | EtClosedException | EtEmptyException | EtBusyException + | EtTimeoutException | IOException e) { e.printStackTrace(); break; } - + try { // Process the events. - for (EtEvent event : events) { - processor.process(event); + for (final EtEvent event : events) { + this.processor.process(event); } - } catch (Exception e) { + } catch (final Exception e) { // If there is an event processing error then print stack trace and continue. e.printStackTrace(); continue; } - + // Disconnect if interrupted. if (Thread.currentThread().isInterrupted()) { break; } - } + } } finally { // Disconnect the ET system. disconnect(); - } - } - - /** - * Disconnect the station. - * This will happen automatically at the end of the {@link #run()} method. - */ - synchronized final void disconnect() { - if (system.alive()) { - if (attachment.isUsable()) { - try { - system.detach(attachment); - } catch (IOException | EtException | EtClosedException | EtDeadException e) { - e.printStackTrace(); - } - } - system.close(); - } - } - - /** - * Wake up the station if it is blocked which will cause it to disconnect. + } + } + + /** + * Setup this station for receiving events. + */ + protected void setup() { + + if (!this.system.alive()) { + try { + this.system.open(); + } catch (IOException | EtException | EtTooManyException e) { + throw new RuntimeException("Failed to open ET system.", e); + } + } + + try { + // Create the basic station configuration. + final EtStationConfig stationConfig = new EtStationConfig(); + stationConfig.setFlowMode(EtConstants.stationSerial); + stationConfig.setBlockMode(EtConstants.stationNonBlocking); + + // Setup event selection. + if (this.select != null) { + stationConfig.setSelect(this.select); + stationConfig.setSelectMode(EtConstants.stationSelectMatch); + } + + // Create station and attach to the ET system. + this.station = this.system.createStation(stationConfig, this.name, this.stationPosition); + this.attachment = this.system.attach(this.station); + + } catch (final Exception e) { + // Any errors during setup are re-thrown. + throw new RuntimeException(e); + } + } + + /** + * Wake up the station if it is blocked, which will cause it to disconnect. */ public final synchronized void wakeUp() { - if (system.alive()) { - if (attachment.isUsable()) { - try { - system.wakeUpAll(station); + if (this.system.alive()) { + if (this.attachment.isUsable()) { + try { + this.system.wakeUpAll(this.station); } catch (IOException | EtException | EtClosedException e) { e.printStackTrace(); - } + } } } } Modified: java/trunk/record-util/src/main/java/org/hps/record/et/PreStartProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/et/PreStartProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/et/PreStartProcessor.java Mon Apr 13 17:23:55 2015 @@ -9,23 +9,38 @@ import org.jlab.coda.jevio.EvioReader; /** - * @author Jeremy McCormick <[log in to unmask]> + * An ET processor that will activate the conditions system from PRESTART events. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ +// FIXME: This class is currently unused in HPS Java. public class PreStartProcessor extends EtEventProcessor { - String detectorName; - EvioDetectorConditionsProcessor conditionsProcessor; - - public PreStartProcessor(String detectorName) { - this.detectorName = detectorName; + /** + * The EVIO processor that will activate the conditions system. + */ + private final EvioDetectorConditionsProcessor conditionsProcessor; + + /** + * Class constructor. + * + * @param detectorName the name of the detector model + */ + public PreStartProcessor(final String detectorName) { this.conditionsProcessor = new EvioDetectorConditionsProcessor(detectorName); } - - public void process(EtEvent event) { + + /** + * Process an ET event and activate the conditions system if applicable. + * + * @param event the <code>EtEvent</code> to process + */ + @Override + public void process(final EtEvent event) { EvioEvent evioEvent = null; try { evioEvent = new EvioReader(event.getDataBuffer()).parseNextEvent(); - conditionsProcessor.startRun(evioEvent); + this.conditionsProcessor.startRun(evioEvent); } catch (IOException | EvioException e) { throw new RuntimeException(e); } Added: java/trunk/record-util/src/main/java/org/hps/record/et/package-info.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/et/package-info.java (added) +++ java/trunk/record-util/src/main/java/org/hps/record/et/package-info.java Mon Apr 13 17:23:55 2015 @@ -0,0 +1,6 @@ +/** + * ET record processing utilities. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ +package org.hps.record.et; Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioDetectorConditionsProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioDetectorConditionsProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioDetectorConditionsProcessor.java Mon Apr 13 17:23:55 2015 @@ -7,63 +7,78 @@ /** * <p> - * This is an {@link EvioEventProcessor} for initializing the conditions system - * from EVIO events. - * <p> - * The {@link #startRun(EvioEvent)} method will setup conditions from the pre start - * events. - * <p> - * The {@link #process(EvioEvent)} method will setup conditions from a head bank - * if it is present in the event. - * - * @author Jeremy McCormick <[log in to unmask]> + * This is an {@link EvioEventProcessor} for initializing the conditions system from EVIO events. The + * {@link #startRun(EvioEvent)} method will setup conditions from PRESTART events. The {@link #process(EvioEvent)} + * method will setup conditions from a head bank, if it is present in the event. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public class EvioDetectorConditionsProcessor extends EvioEventProcessor { - private String detectorName; - - public EvioDetectorConditionsProcessor(String detectorName) { + /** + * The name of the detector model. + */ + private final String detectorName; + + /** + * Class constructor. + * + * @param detectorName the name of the detector model + */ + public EvioDetectorConditionsProcessor(final String detectorName) { if (detectorName == null) { throw new IllegalArgumentException("The detectorName argument is null."); } this.detectorName = detectorName; } - + + /** + * Process an <code>EvioEvent</code> and activate the conditions system if applicable. + * + * @param evioEvent the <code>EvioEvent</code> to process + */ @Override - public void process(EvioEvent evioEvent) throws Exception { + public void process(final EvioEvent evioEvent) throws Exception { // Get the head head bank from event. - BaseStructure headBank = EvioEventUtilities.getHeadBank(evioEvent); - + final BaseStructure headBank = EvioEventUtilities.getHeadBank(evioEvent); + // Is the head bank present? - if (headBank != null) { - + if (headBank != null) { + // Get the run number from the head bank. - int runNumber = headBank.getIntData()[1]; + final int runNumber = headBank.getIntData()[1]; // Initialize the conditions system from the detector name and run number. try { - ConditionsManager.defaultInstance().setDetector(detectorName, runNumber); - } catch (ConditionsNotFoundException e) { + ConditionsManager.defaultInstance().setDetector(this.detectorName, runNumber); + } catch (final ConditionsNotFoundException e) { throw new RuntimeException("Error setting up conditions from EVIO head bank.", e); - } - } + } + } } + /** + * Start of run action. + * <p> + * This will only activate if the evioEvent is a PRESTART event. + * + * @param evioEvent the <code>EvioEvent</code> to process + */ @Override - public void startRun(EvioEvent evioEvent) { - //System.out.println("EvioDetectorConditionsProcessor.startRun"); + public void startRun(final EvioEvent evioEvent) { + // System.out.println("EvioDetectorConditionsProcessor.startRun"); if (EvioEventUtilities.isPreStartEvent(evioEvent)) { // Get the pre start event's data bank. - int[] data = EvioEventUtilities.getControlEventData(evioEvent); - + final int[] data = EvioEventUtilities.getControlEventData(evioEvent); + // Get the run number from the bank. - int runNumber = data[1]; - + final int runNumber = data[1]; + // Initialize the conditions system from the detector name and run number. try { - //System.out.println(" setting up conditions from pre start: " + detectorName + " #" + runNumber); - ConditionsManager.defaultInstance().setDetector(detectorName, runNumber); - } catch (ConditionsNotFoundException e) { + // System.out.println(" setting up conditions from pre start: " + detectorName + " #" + runNumber); + ConditionsManager.defaultInstance().setDetector(this.detectorName, runNumber); + } catch (final ConditionsNotFoundException e) { throw new RuntimeException("Error setting up conditions from EVIO pre start event.", e); } } Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventConstants.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventConstants.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventConstants.java Mon Apr 13 17:23:55 2015 @@ -1,32 +1,94 @@ package org.hps.record.evio; -public class EvioEventConstants { - - // This is the old tag for physics events. +/** + * This is a set of static EVIO event constants. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ +public final class EvioEventConstants { + + /** + * END event tag. + */ + public static final int END_EVENT_TAG = 20; + + /** + * EPICS bank tag. + */ + public static final int EPICS_BANK_TAG = 57620; + + /** + * EPICS 20 second event tag. + */ + // FIXME: This is unused and not handled in event processing. + public static final int EPICS_BANK_TAG_20s = -1; + + /** + * EPICS 2 second event tag. + */ + // FIXME: This is unused and not handled in event processing. + public static final int EPICS_BANK_TAG_2s = -1; + + /** + * EPICS event tag. + */ + public static final int EPICS_EVENT_TAG = 31; + + /** + * Event ID bank tag. + */ + public static final int EVENTID_BANK_TAG = 0xC000; + + /** + * GO event tag. + */ + public static final int GO_EVENT_TAG = 18; + + /** + * Bank tag for header bank with run and event numbers in physics events. + */ + public static final int HEAD_BANK_TAG = 0xe10F; + + /** + * Pause event tag. + */ + // FIXME: Not generally handled or used in event processing. + public static final int PAUSE_EVENT_TAG = 19; + + /** + * This is the old tag for physics events. + */ public static final int PHYSICS_EVENT_TAG = 1; - - // CODA control event tags. + + /** + * Event tags greater than or equal to this will be physics events. + */ + public static final int PHYSICS_START_TAG = 32; + + /** + * PRESTART event tag. + */ + public static final int PRESTART_EVENT_TAG = 17; + + /** + * Tag of the scalars integer bank, which is a child of the crate bank. + */ + public static final int SCALARS_BANK_TAG = 57621; + + /** + * Tag of the scalars crate bank, which is a child of the top bank. + */ + public static final int SCALARS_CRATE_TAG = 39; + + /** + * CODA SYNC event tag. + */ public static final int SYNC_EVENT_TAG = 16; - public static final int PRESTART_EVENT_TAG = 17; - public static final int GO_EVENT_TAG = 18; - public static final int PAUSE_EVENT_TAG = 19; - public static final int END_EVENT_TAG = 20; - - // Special tag for events with EPICS scalars. - public static final int EPICS_EVENT_TAG = 31; - - // Event tags greater than or equal to this will be physics events. - public static final int PHYSICS_START_TAG = 32; - - public static final int EVENTID_BANK_TAG = 0xC000; - - // Bank tag for header bank with run and event numbers in physics events. - public static final int HEAD_BANK_TAG = 0xe10F; - - public static final int EPICS_BANK_TAG = 57620; - public static final int EPICS_BANK_TAG_2s = -1; - public static final int EPICS_BANK_TAG_20s = -1; - //public static final int EPICS_BANK_TAG_2s = -1; - //public static final int EPICS_BANK_TAG_20s = -1; - + + /** + * Disallow class instantiation. + */ + private EvioEventConstants() { + throw new UnsupportedOperationException("Do not instantiate this class."); + } } Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventProcessor.java Mon Apr 13 17:23:55 2015 @@ -4,8 +4,9 @@ import org.jlab.coda.jevio.EvioEvent; /** - * This is the basic abstract class that processors of - * <tt>EvioEvent</tt> objects should extend. + * This is the basic abstract class that processors of <code>EvioEvent</code> objects should extend. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ -public abstract class EvioEventProcessor extends AbstractRecordProcessor<EvioEvent> { +public abstract class EvioEventProcessor extends AbstractRecordProcessor<EvioEvent> { } Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventQueue.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventQueue.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventQueue.java Mon Apr 13 17:23:55 2015 @@ -5,17 +5,26 @@ /** * A dynamic queue providing <tt>EvioEvent</tt> objects to a loop. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public final class EvioEventQueue extends AbstractRecordQueue<EvioEvent> { - public EvioEventQueue(long timeoutMillis, int maxSize) { + /** + * Class constructor. + * + * @param timeoutMillis the timeout for accessing records from the queue + * @param maxSize the maximum queue size + */ + public EvioEventQueue(final long timeoutMillis, final int maxSize) { super(timeoutMillis, maxSize); } - - /** - * Get the class of the supplied records. - * @return The class of the supplied records. - */ + + /** + * Get the class of the supplied records. + * + * @return the class of the supplied records + */ @Override public Class<EvioEvent> getRecordClass() { return EvioEvent.class; Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventUtilities.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventUtilities.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventUtilities.java Mon Apr 13 17:23:55 2015 @@ -1,126 +1,33 @@ package org.hps.record.evio; -import static org.hps.record.evio.EvioEventConstants.*; +import static org.hps.record.evio.EvioEventConstants.END_EVENT_TAG; +import static org.hps.record.evio.EvioEventConstants.EPICS_EVENT_TAG; +import static org.hps.record.evio.EvioEventConstants.GO_EVENT_TAG; +import static org.hps.record.evio.EvioEventConstants.PAUSE_EVENT_TAG; +import static org.hps.record.evio.EvioEventConstants.PHYSICS_START_TAG; +import static org.hps.record.evio.EvioEventConstants.PRESTART_EVENT_TAG; +import static org.hps.record.evio.EvioEventConstants.SYNC_EVENT_TAG; import org.jlab.coda.jevio.BaseStructure; import org.jlab.coda.jevio.EvioEvent; /** - * This is a set of basic static utility methods on <code>EvioEvent</code> - * objects. + * This is a set of basic static utility methods for <code>EvioEvent</code> objects. * - * @author Jeremy McCormick <[log in to unmask]> + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public final class EvioEventUtilities { - - private EvioEventUtilities() { - } - - /** - * Get the event tag from the header bank. - * @param event The input EvioEvent. - * @return The event tag from the header bank. - */ - public static int getEventTag(EvioEvent event) { - return event.getHeader().getTag(); - } - - /** - * Check if the EVIO event is a PRE START event indicating the beginning of - * a run. - * - * @param event The EvioEvent. - * @return True if the event is a pre start event. - */ - public static boolean isPreStartEvent(EvioEvent event) { - return event.getHeader().getTag() == PRESTART_EVENT_TAG; - } - - /** - * Check if the EVIO event is a GO event. - * - * @param event The EvioEvent. - * @return True if the event is a go event. - */ - public static boolean isGoEvent(EvioEvent event) { - return event.getHeader().getTag() == GO_EVENT_TAG; - } - - /** - * Check if the EVIO event is a PAUSE event. - * - * @param event The EvioEvent. - * @return True if the event is a pause event. - */ - public static boolean isPauseEvent(EvioEvent event) { - return event.getHeader().getTag() == PAUSE_EVENT_TAG; - } - - /** - * Check if this event is an END event. - * - * @param event The EvioEvent. - * @return True if this event is an end event. - */ - public static boolean isEndEvent(EvioEvent event) { - return event.getHeader().getTag() == END_EVENT_TAG; - } - - /** - * Check if this event has physics data. - * - * @param event The EvioEvent. - * @return True if this event is a physics event. - */ - public static boolean isPhysicsEvent(EvioEvent event) { - return (event.getHeader().getTag() >= PHYSICS_START_TAG || - event.getHeader().getTag() < SYNC_EVENT_TAG); - // return event.getHeader().getTag() == PHYSICS_EVENT_TAG; - } - - /** - * Check if this event is a SYNC event. - * - * @param event The EvioEvent. - * @return True if this event is a SYNC event. - */ - public static boolean isSyncEvent(EvioEvent event) { - return event.getHeader().getTag() == SYNC_EVENT_TAG; - } - - /** - * Check if this event is an EPICS event containing scalar data. - * - * @param event The EvioEvent. - * @return True if this event is an EPICS event. - */ - public static boolean isEpicsEvent(EvioEvent event) { - return event.getHeader().getTag() == EPICS_EVENT_TAG; - } - - /** - * True if <code>event</code> is an EVIO control event. - * @return True if event is a control event. - */ - public static boolean isControlEvent(EvioEvent event) { - return isPreStartEvent(event) || - isGoEvent(event) || - isPauseEvent(event) || - isEndEvent(event) || - isSyncEvent(event) || - isEpicsEvent(event); - } /** * Extract the CODA run data stored in a control event. * - * @param event The EvioEvent. - * @return The int data for the control event. Null if the event is not a - * control event, or the int bank for the control event is not found. + * @param event the <code>EvioEvent</code> to handle + * @return the <code>int</code> data array for the control event or <code>null</code> if the event is not a control + * event or data bank is not found */ - public static int[] getControlEventData(EvioEvent event) { - int eventTag = event.getHeader().getTag(); - switch (eventTag) { //if the event's not a control event, stop + public static int[] getControlEventData(final EvioEvent event) { + final int eventTag = event.getHeader().getTag(); + switch (eventTag) { // if the event's not a control event, stop case PRESTART_EVENT_TAG: case PAUSE_EVENT_TAG: case END_EVENT_TAG: @@ -131,30 +38,42 @@ return null; } - int[] data = event.getIntData(); - if (data != null) { //found the data in the top-level bank + final int[] data = event.getIntData(); + if (data != null) { // found the data in the top-level bank return data; - } else { //data is not in event bank; look for the data bank whose tag matches the event type - for (BaseStructure bank : event.getChildrenList()) { + } else { // data is not in event bank; look for the data bank whose tag matches the event type + for (final BaseStructure bank : event.getChildrenList()) { if (bank.getHeader().getTag() == eventTag) { - return bank.getIntData(); //return whatever int data this bank has + return bank.getIntData(); // return whatever int data this bank has } } - return null; //we didn't find the bank; give up + return null; // we didn't find the bank; give up } } - + + /** + * Get the event tag from the header bank. + * + * @param event the input <code>EvioEvent</code> + * @return the event tag from the header bank + */ + public static int getEventTag(final EvioEvent event) { + return event.getHeader().getTag(); + } + /** * Get the head bank with event header that includes run number. + * <p> * This is a nested bank. - * @param evioEvent The EVIO event. - * @return The head bank or null if does not exist in this event. + * + * @param evioEvent the <code>EvioEvent</code> with the head bank + * @return the head bank or <code>null</code> if it does not exist */ - public static BaseStructure getHeadBank(EvioEvent evioEvent) { + public static BaseStructure getHeadBank(final EvioEvent evioEvent) { if (evioEvent.getChildCount() > 0) { - for (BaseStructure topBank : evioEvent.getChildrenList()) { + for (final BaseStructure topBank : evioEvent.getChildrenList()) { if (topBank.getChildrenList() != null) { - for (BaseStructure nestedBank : topBank.getChildrenList()) { + for (final BaseStructure nestedBank : topBank.getChildrenList()) { if (nestedBank.getHeader().getTag() == EvioEventConstants.HEAD_BANK_TAG) { return nestedBank; } @@ -162,20 +81,22 @@ } } } - return null; + return null; } - + /** * Get the run number from an EVIO event. - * @return The run number. + * + * @return the run number + * @throws IllegalArgumentException if event does not have a head bank */ - public static int getRunNumber(EvioEvent event) { + public static int getRunNumber(final EvioEvent event) { if (isControlEvent(event)) { return getControlEventData(event)[1]; } else if (isPhysicsEvent(event)) { - BaseStructure headBank = EvioEventUtilities.getHeadBank(event); - if (headBank != null) { - return headBank.getIntData()[1]; + final BaseStructure headBank = EvioEventUtilities.getHeadBank(event); + if (headBank != null) { + return headBank.getIntData()[1]; } else { throw new IllegalArgumentException("Head bank is missing from physics event."); } @@ -184,4 +105,93 @@ throw new IllegalArgumentException("Wrong event type: " + event.getHeader().getTag()); } } + + /** + * Return <code>true</code> if <code>event</code> is a CODA control event such as a PRESTART or GO event. + * + * @return <code>true</code> if event is a control event + */ + public static boolean isControlEvent(final EvioEvent event) { + return isPreStartEvent(event) || isGoEvent(event) || isPauseEvent(event) || isEndEvent(event) + || isSyncEvent(event) || isEpicsEvent(event); + } + + /** + * Check if this event is an END event. + * + * @param event the <code>EvioEvent</code> to check + * @return <code>true</code> if this event is an END event. + */ + public static boolean isEndEvent(final EvioEvent event) { + return event.getHeader().getTag() == END_EVENT_TAG; + } + + /** + * Check if this event is an EPICS event. + * + * @param event the <code>EvioEvent</code> to check + * @return <code>true</code> if this event is an EPICS event + */ + public static boolean isEpicsEvent(final EvioEvent event) { + return event.getHeader().getTag() == EPICS_EVENT_TAG; + } + + /** + * Check if the event is a GO event. + * + * @param event the <code>EvioEvent</code> to check + * @return <code>true</code> if the event is a GO event. + */ + public static boolean isGoEvent(final EvioEvent event) { + return event.getHeader().getTag() == GO_EVENT_TAG; + } + + /** + * Check if the EVIO event is a PAUSE event. + * + * @param event the <code>EvioEvent</code> to check + * @return <code>true</code> if the event is a PAUSE event. + */ + public static boolean isPauseEvent(final EvioEvent event) { + return event.getHeader().getTag() == PAUSE_EVENT_TAG; + } + + /** + * Check if this event has physics data. + * + * @param event the <code>EvioEvent</code> to check + * @return <code>true</code> if this event is a physics event + */ + public static boolean isPhysicsEvent(final EvioEvent event) { + // This checks if the tag is outside the CODA control event range. + return event.getHeader().getTag() >= PHYSICS_START_TAG || event.getHeader().getTag() < SYNC_EVENT_TAG; + // return event.getHeader().getTag() == PHYSICS_EVENT_TAG; + } + + /** + * Check if the EVIO event is a PRESTART event indicating the beginning of a run. + * + * @param event the <code>EvioEvent</code> to check + * @return <code>true</code> if the event is a PRESTART event + */ + public static boolean isPreStartEvent(final EvioEvent event) { + return event.getHeader().getTag() == PRESTART_EVENT_TAG; + } + + /** + * Check if this event is a SYNC event. + * + * @param event the <code>EvioEvent</code> to check + * @return <code>true</code> if this event is a SYNC event + */ + public static boolean isSyncEvent(final EvioEvent event) { + return event.getHeader().getTag() == SYNC_EVENT_TAG; + } + + /** + * Class should not be instantiated. + */ + private EvioEventUtilities() { + throw new UnsupportedOperationException("Do not instantiate this class."); + } } Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileProducer.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileProducer.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileProducer.java Mon Apr 13 17:23:55 2015 @@ -21,23 +21,26 @@ /** * A utility class for streaming an EVIO file to an ET server. - * - * NOTE: Original version was copied from the CODA group's ET java module. + * <p> + * Original version was copied from the CODA group's ET java module. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ // TODO: Add option to set number of events in the put array. public final class EvioFileProducer { - private List<File> evioFiles = new ArrayList<File>(); - private EvioReader reader; - private ByteBuffer byteBuffer; - private String etName, host; - private int port = EtConstants.serverPort; - private int group = 1; - private int size = 10000; // Default event size. - private int delay = 0; + /** + * Flag to turn on/off debug print. + */ private static final boolean debug = false; - EvioFileProducer() { + /** + * The externally accessible main method. + * + * @param args The command line arguments. + */ + public static void main(final String[] args) { + new EvioFileProducer().doMain(args); // call wrapper method } /** @@ -45,8 +48,7 @@ */ private static void usage() { System.out.println("\nUsage: java Producer -f <et name> -e <evio file> [-p <server port>] [-host <host>]" - + " [-d <delay in millisec>] [-g <group #>]\n\n" - + " -f ET system's name\n" + + " [-d <delay in millisec>] [-g <group #>]\n\n" + " -f ET system's name\n" + " -s size in bytes for requested events\n" + " -p port number for a udp broadcast\n" + " -g group number of new events to get\n" @@ -57,83 +59,129 @@ } /** + * The byte buffer used to transfer data from EVIO to ET. + */ + private ByteBuffer byteBuffer; + + /** + * A delay in milliseconds between put operations. + */ + private int delay = 0; + + /** + * The ET system name which generally maps to a buffer file. + */ + private String etName; + + /** + * The list of input EVIO files. + */ + private final List<File> evioFiles = new ArrayList<File>(); + + /** + * This is used for a "group" value when doing put but not sure what it actually does. + */ + private int group = 1; + + /** + * The server host name. + */ + private String host; + + /** + * The server's network port. + */ + private int port = EtConstants.serverPort; + + /** + * The EVIO reader used to read the input EVIO events. + */ + private EvioReader reader; + + /** + * The default ET event size. + */ + // FIXME: Should be a lot bigger? + private int size = 10000; // Default event size. + + /** + * Class constructor. + */ + private EvioFileProducer() { + } + + /** * Copy byte buffer to an <code>EtEvent</code>. + * * @param event The target EtEvent. */ - public void copyToEtEvent(EtEvent event) { - event.getDataBuffer().put(byteBuffer); - } - - /** - * The externally accessible main method. + public void copyToEtEvent(final EtEvent event) { + event.getDataBuffer().put(this.byteBuffer); + } + + /** + * Wrapper method called in main. + * * @param args The command line arguments. */ - public static void main(String[] args) { - (new EvioFileProducer()).doMain(args); // call wrapper method - } - - /** - * Wrapper method called in main. - * @param args The command line arguments. - */ - public void doMain(String[] args) { + public void doMain(final String[] args) { try { for (int i = 0; i < args.length; i++) { if (args[i].equalsIgnoreCase("-e")) { - //evioFileName = new String(args[++i]); - evioFiles.add(new File(args[++i])); + // evioFileName = new String(args[++i]); + this.evioFiles.add(new File(args[++i])); } else if (args[i].equalsIgnoreCase("-f")) { - etName = args[++i]; + this.etName = args[++i]; } else if (args[i].equalsIgnoreCase("-host")) { - host = args[++i]; + this.host = args[++i]; } else if (args[i].equalsIgnoreCase("-p")) { try { - port = Integer.parseInt(args[++i]); - if ((port < 1024) || (port > 65535)) { + this.port = Integer.parseInt(args[++i]); + if (this.port < 1024 || this.port > 65535) { System.out.println("Port number must be between 1024 and 65535."); usage(); return; } - } catch (NumberFormatException ex) { + } catch (final NumberFormatException ex) { System.out.println("Did not specify a proper port number."); usage(); return; } } else if (args[i].equalsIgnoreCase("-s")) { try { - size = Integer.parseInt(args[++i]); - if (size < 1) { + this.size = Integer.parseInt(args[++i]); + if (this.size < 1) { System.out.println("Size needs to be positive int."); usage(); return; } - } catch (NumberFormatException ex) { + } catch (final NumberFormatException ex) { System.out.println("Did not specify a proper size."); usage(); return; } } else if (args[i].equalsIgnoreCase("-g")) { try { - group = Integer.parseInt(args[++i]); - if ((group < 1) || (group > 10)) { + this.group = Integer.parseInt(args[++i]); + if (this.group < 1 || this.group > 10) { System.out.println("Group number must be between 0 and 10."); usage(); return; } - } catch (NumberFormatException ex) { + } catch (final NumberFormatException ex) { System.out.println("Did not specify a proper group number."); usage(); return; } } else if (args[i].equalsIgnoreCase("-d")) { try { - delay = Integer.parseInt(args[++i]); - if (delay < 1) { + this.delay = Integer.parseInt(args[++i]); + if (this.delay < 1) { System.out.println("delay must be > 0."); usage(); return; } - } catch (NumberFormatException ex) { + } catch (final NumberFormatException ex) { System.out.println("Did not specify a proper delay."); usage(); return; @@ -144,18 +192,18 @@ } } - if (host == null) { - //host = EtConstants.hostAnywhere; - host = InetAddress.getLocalHost().getHostName(); + if (this.host == null) { + // host = EtConstants.hostAnywhere; + this.host = InetAddress.getLocalHost().getHostName(); } // ET name is required. - if (etName == null) { + if (this.etName == null) { System.out.println("EVIO file name argument is required"); usage(); return; } - + if (this.evioFiles.size() == 0) { System.out.println("At least one input EVIO file is required."); usage(); @@ -164,7 +212,7 @@ // Check existence of EVIO files. System.out.println("EVIO input files ..."); - for (File evioFile : evioFiles) { + for (final File evioFile : this.evioFiles) { System.out.println(evioFile.getPath()); if (!evioFile.exists()) { System.err.println("EVIO file does not exist: " + evioFile.getPath()); @@ -173,25 +221,25 @@ } // Setup ET system with the command line config. - EtSystemOpenConfig config = new EtSystemOpenConfig(etName, host, port); - EtSystem sys = new EtSystem(config, EtConstants.debugInfo); + final EtSystemOpenConfig config = new EtSystemOpenConfig(this.etName, this.host, this.port); + final EtSystem sys = new EtSystem(config, EtConstants.debugInfo); sys.open(); - EtStation gc = sys.stationNameToObject("GRAND_CENTRAL"); - EtAttachment att = sys.attach(gc); + final EtStation gc = sys.stationNameToObject("GRAND_CENTRAL"); + final EtAttachment att = sys.attach(gc); // array of events EtEvent[] mevs; - + // Loop over input EVIO file list. - for (File evioFile : evioFiles) { - + for (final File evioFile : this.evioFiles) { + // Open EVIO reader. System.out.println("Opening next EVIO file: " + evioFile.getPath()); - reader = new EvioReader(evioFile.getPath(), false); + this.reader = new EvioReader(evioFile.getPath(), false); // Print number of events. if (debug) { - System.out.println("EVIO file opened with " + reader.getEventCount() + " events."); + System.out.println("EVIO file opened with " + this.reader.getEventCount() + " events."); } // Ref to current EVIO event. @@ -199,12 +247,12 @@ // Event sequence number; starts with 1. int eventCount = 0; - + // Loop until event source is exhausted. while (true) { // Get next event. - event = reader.nextEvent(); + event = this.reader.nextEvent(); ++eventCount; if (eventCount % 1000 == 0) { System.out.println("EvioFileProducer - event <" + eventCount + ">"); @@ -212,62 +260,64 @@ if (event == null) { break; } - - // Try to parse the next event. - try { - reader.parseEvent(event); + + // Try to parse the next event. + try { + this.reader.parseEvent(event); if (debug) { - System.out.println("event #" + event.getEventNumber() + " is " + event.getTotalBytes() + " bytes"); - } - } catch (Exception e) { + System.out.println("event #" + event.getEventNumber() + " is " + event.getTotalBytes() + + " bytes"); + } + } catch (final Exception e) { e.printStackTrace(); - System.out.println("Error making EVIO event with sequence number <" + eventCount + "> in file <" + evioFile.getPath() + ">."); + System.out.println("Error making EVIO event with sequence number <" + eventCount + + "> in file <" + evioFile.getPath() + ">."); // Attempt to recover from errors by skipping to next event if there are exceptions. continue; } if (debug) { - System.out.println("new events - size=" + size + "; group=" + group); - } - - int eventTag = EvioEventUtilities.getEventTag(event); - - // Create a new array of ET events. This always has one event. - mevs = sys.newEvents( - att, // attachment + System.out.println("new events - size=" + this.size + "; group=" + this.group); + } + + final int eventTag = EvioEventUtilities.getEventTag(event); + + // Create a new array of ET events. This always has one event. + mevs = sys.newEvents(att, // attachment Mode.SLEEP, // wait mode false, // create a buffer - 0, // delay + 0, // delay 1, // number of events - size, // size of event but overwritten later - group); // group number; default value is arbitrary - + this.size, // size of event but overwritten later + this.group); // group number; default value is arbitrary + // Create control data array for event selection. - int[] control = new int[EtConstants.stationSelectInts]; + final int[] control = new int[EtConstants.stationSelectInts]; Arrays.fill(control, eventTag); mevs[0].setControl(control); - + // Delay for X millis if applicable. - if (delay > 0) { - Thread.sleep(delay); + if (this.delay > 0) { + Thread.sleep(this.delay); } // Write the next EVIO event to the EtEvent's buffer. - ByteBuffer buf = mevs[0].getDataBuffer(); + final ByteBuffer buf = mevs[0].getDataBuffer(); buf.order(ByteOrder.nativeOrder()); - EventWriter writer = new EventWriter(buf, 100000, 100, null, null); + final EventWriter writer = new EventWriter(buf, 100000, 100, null, null); writer.writeEvent(event); try { writer.close(); - } catch (Exception e) { + } catch (final Exception e) { System.out.println("Caught exception while closing writer."); e.printStackTrace(); } mevs[0].setLength(buf.position()); mevs[0].setByteOrder(ByteOrder.nativeOrder()); if (debug) { - for (EtEvent mev : mevs) { - System.out.println("event length = " + mev.getLength() + ", remaining bytes: " + mev.getDataBuffer().remaining()); + for (final EtEvent mev : mevs) { + System.out.println("event length = " + mev.getLength() + ", remaining bytes: " + + mev.getDataBuffer().remaining()); } } @@ -281,13 +331,13 @@ } } - reader.close(); + this.reader.close(); } // Cleanup. - sys.close(); - - } catch (Exception e) { + sys.close(); + + } catch (final Exception e) { throw new RuntimeException(e); } } Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileSource.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileSource.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileSource.java Mon Apr 13 17:23:55 2015 @@ -12,45 +12,146 @@ import org.jlab.coda.jevio.EvioReader; /** - * A basic implementation of an <tt>AbstractRecordSource</tt> for supplying <tt>EvioEvent</tt> - * objects to a loop from EVIO files. - * + * A basic implementation of an <tt>AbstractRecordSource</tt> for supplying <tt>EvioEvent</tt> objects to a loop from + * EVIO files. + * <p> * Unlike the LCIO record source, it has no rewind or indexing capabilities. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ public final class EvioFileSource extends AbstractRecordSource { - EvioEvent currentEvent; - EvioReader reader; - List<File> files = new ArrayList<File>(); - int fileIndex = 0; - boolean atEnd; + /** + * The current event. + */ + private EvioEvent currentEvent; + + /** + * The current file index. + */ + private int fileIndex = 0; + + /** + * The list of input data files. + */ + private final List<File> files = new ArrayList<File>(); + + /** + * The reader to use for reading and parsing the EVIO data. + */ + private EvioReader reader; + + /** + * Constructor taking a single EVIO file. + * + * @param file the EVIO file + */ + public EvioFileSource(final File file) { + this.files.add(file); + openReader(); + } /** * Constructor taking a list of EVIO files. - * @param files The list of EVIO files. + * + * @param files the list of EVIO files */ - public EvioFileSource(List<File> files) { + public EvioFileSource(final List<File> files) { this.files.addAll(files); openReader(); } /** - * Constructor taking a single EVIO file. - * @param file The EVIO file. + * Close the current reader. */ - public EvioFileSource(File file) { - this.files.add(file); - openReader(); + private void closeReader() { + try { + this.reader.close(); + } catch (final IOException e) { + throw new RuntimeException(e); + } } /** - * Open the EVIO reader on the current file from the list. - * @throws RuntimeException if an EvioException or IOException occurs while opening file. + * Return <code>true</code> if there are no more files to open from the list. + * + * @return <code>true</code> if there are no more files in the list + */ + boolean endOfFiles() { + return this.fileIndex > this.files.size() - 1; + } + + /** + * Get the current record which is an <code>EvioEvent</code>. + * + * @return the current record + */ + @Override + public Object getCurrentRecord() throws IOException { + return this.currentEvent; + } + + /** + * Return <code>true</code> if there is a current record loaded. + * + * @return <code>true</code> if there is a current record loaded. + */ + @Override + public boolean hasCurrent() { + return this.currentEvent != null; + } + + /** + * Return <code>true</code> if there is a next record. + * + * @return <code>true</code> if there are more records to load + */ + @Override + public boolean hasNext() { + try { + return this.reader.getNumEventsRemaining() != 0; + } catch (IOException | EvioException e) { + throw new RuntimeException("Error getting num remaining events."); + } + } + + /** + * Load the next record. + * + * @throws NoSuchRecordException if source is exhausted + * @throws IOException if there is an error creating the next <code>EvioEvent</code> + */ + @Override + public void next() throws IOException, NoSuchRecordException { + for (;;) { + try { + this.currentEvent = this.reader.parseNextEvent(); + } catch (final EvioException e) { + throw new IOException(e); + } + if (this.currentEvent == null) { + closeReader(); + this.fileIndex++; + if (!endOfFiles()) { + openReader(); + continue; + } else { + throw new NoSuchRecordException(); + } + } + return; + } + } + + /** + * Open the next file in the list with the reader. + * + * @throws RuntimeException if an <code>EvioException</code> or <code>IOException</code> occurs while opening file */ private void openReader() { try { - System.out.println("Opening reader for file " + files.get(fileIndex) + " ..."); - reader = new EvioReader(files.get(fileIndex), false); + System.out.println("Opening reader for file " + this.files.get(this.fileIndex) + " ..."); + this.reader = new EvioReader(this.files.get(this.fileIndex), false); System.out.println("Done opening file."); } catch (EvioException | IOException e) { throw new RuntimeException(e); @@ -58,89 +159,12 @@ } /** - * Close the current reader. - */ - private void closeReader() { - try { - reader.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * Get the current record which is an <code>EvioEvent</code>. - * @return The current record.s - */ - @Override - public Object getCurrentRecord() throws IOException { - return currentEvent; - } - - /** - * True if there are no more files to open in the list. - * @return True if there are no more files in the list. - */ - boolean endOfFiles() { - return fileIndex > (files.size() - 1); - } - - /** - * Load the next record. - * @throws NoSuchRecordException if source is exhausted. - * @throws IOException if there is an error creating the next EvioEvent. - */ - @Override - public void next() throws IOException, NoSuchRecordException { - for (;;) { - try { - currentEvent = reader.parseNextEvent(); - } catch (EvioException e) { - throw new IOException(e); - } - if (currentEvent == null) { - closeReader(); - fileIndex++; - if (!endOfFiles()) { - openReader(); - continue; - } else { - atEnd = true; - throw new NoSuchRecordException(); - } - } - return; - } - } - - /** - * True because source supports loading next record. - * @return True because source supports loading next record. + * Returns <code>true</code> to indicate next record capability is supported. + * + * @return <code>true</code> to indicate next record capability is supported */ @Override public boolean supportsNext() { return true; } - - /** - * True if there is a current record loaded. - * @return True if there is a current record loaded. - */ - @Override - public boolean hasCurrent() { - return currentEvent != null; - } - - /** - * True if there are more records to load. - * @return True if there are more records to load. - */ - @Override - public boolean hasNext() { - try { - return reader.getNumEventsRemaining() != 0; - } catch (IOException | EvioException e) { - throw new RuntimeException("Error getting num remaining events."); - } - } } Added: java/trunk/record-util/src/main/java/org/hps/record/evio/package-info.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/package-info.java (added) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/package-info.java Mon Apr 13 17:23:55 2015 @@ -0,0 +1,6 @@ +/** + * EVIO record processing utilities. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ +package org.hps.record.evio; Modified: java/trunk/record-util/src/main/java/org/hps/record/lcio/LcioEventQueue.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/lcio/LcioEventQueue.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/lcio/LcioEventQueue.java Mon Apr 13 17:23:55 2015 @@ -3,45 +3,111 @@ import org.hps.record.AbstractRecordQueue; import org.lcsim.event.EventHeader; -public class LcioEventQueue extends AbstractRecordQueue<EventHeader> { - - public LcioEventQueue(long timeoutMillis, int maxQueueSize) { +/** + * A record queue for LCIO/LCSim events. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ +public class LcioEventQueue extends AbstractRecordQueue<EventHeader> { + + /** + * Class constructor. + * + * @param timeoutMillis the queue timeout in milliseconds + * @param maxQueueSize the maximum queue size + */ + public LcioEventQueue(final long timeoutMillis, final int maxQueueSize) { super(timeoutMillis, maxQueueSize); } - + + /** + * Get the record class. + * + * @return the record class + */ + @Override public Class<?> getRecordClass() { return EventHeader.class; } - + + /** + * Return <code>true</code> if there is a current record. + * + * @return <code>true</code> if there is a current record + */ + @Override + public boolean hasCurrent() { + return this.size() != 0L; + } + + /** + * Return <code>true</code> to indicate there is a next record. + * + * @return <code>true</code> to indicate there is a next record + */ + // FIXME: Should this actually check if the queue has more records? + @Override + public boolean hasNext() { + return true; + } + + /** + * Return <code>true</code> to indicate current record capability is supported. + * + * @return <code>true</code> to indicate current record capability is supported + */ + @Override public boolean supportsCurrent() { return true; } + /** + * Return <code>false</code> to indicate indexing is not supported. + * + * @return <code>false</code> to indicate indexing is not supported. + */ + @Override + public boolean supportsIndex() { + return false; + } + + /** + * Return <code>true</code> to indicate next record capability is supported. + * + * @return <code>true</code> to indicate next record capability is supported + */ + @Override public boolean supportsNext() { return true; } - + + /** + * Return <code>false</code> to indicate previous record capability is not supported. + * + * @return <code>false</code> to indicate previous record capability is not supported + */ + @Override public boolean supportsPrevious() { return false; } - - public boolean supportsIndex() { + + /** + * Return <code>false</code> to indicate rewind is not supported. + * + * @return <code>false</code> to indicate rewind is not supported + */ + @Override + public boolean supportsRewind() { return false; } - + + /** + * Return <code>false</code> to indicate shift operation is not supported. + * + * @return <code>false</code> to indicate shift operation is not supported + */ + @Override public boolean supportsShift() { return false; } - - public boolean supportsRewind() { - return false; - } - - public boolean hasCurrent() { - return this.size() != 0L; - } - - public boolean hasNext() { - return true; - } } Added: java/trunk/record-util/src/main/java/org/hps/record/lcio/package-info.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/lcio/package-info.java (added) +++ java/trunk/record-util/src/main/java/org/hps/record/lcio/package-info.java Mon Apr 13 17:23:55 2015 @@ -0,0 +1,6 @@ +/** + * LCIO record processing utilities. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ +package org.hps.record.lcio; Modified: java/trunk/record-util/src/main/java/org/hps/record/package-info.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/package-info.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/package-info.java Mon Apr 13 17:23:55 2015 @@ -1,18 +1,14 @@ /** - * The package <code>org.hps.record</code> and its sub-packages use the - * <a href="http://java.freehep.org/freehep-record/">FreeHep Record</a> module - * to implement a flexible record processing backend. Its current primary - * usage is providing the record processing chain for the HPS Monitoring Application, - * but it can be used stand-alone outside of that framework. - * - * The primary class for user interaction is the {@link org.hps.record.composite.CompositeLoop} - * class which implements a record loop that can convert <code>EtEvent</code> objects - * to <code>EvioEvent</code> objects and then finally build LCSim event, or <code>EventHeader</event> - * objects from the EVIO, using a series of adapter classes on the loop. The loop implementation - * is flexible so that it may be configured to use an ET server, an EVIO file or an LCIO file for - * the record source. The {@link org.hps.record.composite.CompositeLoopConfiguration} class should be - * used to configure the loop by the user. - * - * @author Jeremy McCormick <[log in to unmask]> + * The package <code>org.hps.record</code> and its sub-packages use the <a + * href="http://java.freehep.org/freehep-record/">FreeHep Record</a> module to implement a flexible record processing + * backend. Its current primary usage is providing the record processing chain for the HPS Monitoring Application, but + * it can be used stand-alone outside of that framework. The primary class for user interaction is the + * {@link org.hps.record.composite.CompositeLoop} class which implements a record loop that can convert + * <code>EtEvent</code> objects to <code>EvioEvent</code> objects and then finally build LCSim event, or + * <code>EventHeader</event> objects from the EVIO, using a series of adapter classes on the loop. The loop implementation + * is flexible so that it may be configured to use an ET server, an EVIO file or an LCIO file for the record source. + * The {@link org.hps.record.composite.CompositeLoopConfiguration} class should be used to configure the loop by the user. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ package org.hps.record; Modified: java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarData.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarData.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarData.java Mon Apr 13 17:23:55 2015 @@ -7,132 +7,142 @@ import org.lcsim.event.GenericObject; /** - * This class encapsulates EVIO scalar data which is simply an array - * of integer values. The exact meaning of each of these integer - * words is defined externally to this class. - * - * @author Jeremy McCormick <[log in to unmask]> + * This class encapsulates EVIO scalar data which is simply an array of integer values. The exact meaning of each of + * these integer words is defined externally to this class. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ -public class ScalarData { - - // The default name for reading and writing the LCIO event collection. +public final class ScalarData { + + /** + * Default name of scalar data collection in LCSim events. + */ static String DEFAULT_SCALAR_DATA_COLLECTION_NAME = "ScalarData"; - - // The scalar data values. - int[] data; - + /** - * This is the no argument constructor which is for package internal use. + * Create a new <code>ScalarData</code> object from an LCIO event, using the default collection name. + * + * @param event the LCIO event data + * @return the <code>ScalarData</code> object or <code>null</code> if there's no scalar data in the event */ - ScalarData() { + public static ScalarData read(final EventHeader event) { + return read(event, DEFAULT_SCALAR_DATA_COLLECTION_NAME); } - - /** - * Create from provided scalar data values. - * @param data The scalar data. - */ - public ScalarData(int[] data) { - this.data = new int[data.length]; - System.arraycopy(data, 0, this.data, 0, data.length); - } - - /** - * Get the number of scalars. - * @return The number of scalars. - */ - public int size() { - return data.length; - } - - /** - * Get the scalar data value at the index. - * @param index The scalar data index. - * @return The scalar data value. - */ - public Integer getValue(int index) { - return data[index]; - } - - /** - * Convert this object to an lcsim {@link org.lcsim.event.GenericObject} for - * persistency to LCIO. - * @return The LCIO GenericObject. - */ - GenericObject toGenericObject() { - ScalarsGenericObject object = new ScalarsGenericObject(); - object.values = data; - return object; - } - - /** - * Load data into this object from an {@link org.lcsim.event.GenericObject} - * read from an LCIO event. - * @param object The GenericObject with the scalar data. - */ - void fromGenericObject(GenericObject object) { - this.data = new int[object.getNInt()]; - for (int index = 0; index < object.getNInt(); index++) { - this.data[index] = object.getIntVal(index); - } - } - - /** - * Write this object out to an LCIO event using the default collection name. - * @param event The output LCIO event. - */ - public void write(EventHeader event) { - write(event, DEFAULT_SCALAR_DATA_COLLECTION_NAME); - } - - /** - * Write this object out to an LCIO event using the given collection name. - * @param event The output LCIO event. - * @param collectionName The name of the collection. - */ - public void write(EventHeader event, String collectionName) { - List<GenericObject> collection = new ArrayList<GenericObject>(); - collection.add(toGenericObject()); - event.put(collectionName, collection, GenericObject.class, 0); - } - - + /** * Create a new object from the data in an LCIO event, using the default collection name. - * @param event The LCIO event data. - * @return The created ScalarData object or null if does not exist in event. + * + * @param event the LCIO event data + * @return the <code>ScalarData</code> object or <code>null</code> if does not exist in event */ - public static ScalarData read(EventHeader event) { - return read(event, DEFAULT_SCALAR_DATA_COLLECTION_NAME); - } - - /** - * Create a new object from the data in an LCIO event, using the default collection name. - * @param event The LCIO event data. - * @return The created ScalarData object or null if does not exist in event. - */ - public static ScalarData read(EventHeader event, String collectionName) { + public static ScalarData read(final EventHeader event, final String collectionName) { ScalarData data = null; if (event.hasCollection(GenericObject.class, collectionName)) { - List<GenericObject> objects = event.get(GenericObject.class, collectionName); + final List<GenericObject> objects = event.get(GenericObject.class, collectionName); data = new ScalarData(); data.fromGenericObject(objects.get(0)); } return data; } - - + /** - * Convert this object to a readable string, which is a list of integer values - * enclosed in braces and separated by commas. + * The scalar data values. */ + private int[] data; + + /** + * This is the no argument constructor which is for package internal use only. + */ + ScalarData() { + } + + /** + * Create from provided scalar data values. + * + * @param data the scalar data + */ + public ScalarData(final int[] data) { + this.data = new int[data.length]; + System.arraycopy(data, 0, this.data, 0, data.length); + } + + /** + * Load data into this object from an {@link org.lcsim.event.GenericObject} read from an LCIO event. + * + * @param object the <code>GenericObject</code> with the scalar data + */ + void fromGenericObject(final GenericObject object) { + this.data = new int[object.getNInt()]; + for (int index = 0; index < object.getNInt(); index++) { + this.data[index] = object.getIntVal(index); + } + } + + /** + * Get the scalar data value at the index. + * + * @param index the scalar data index + * @return the scalar data value + */ + public Integer getValue(final int index) { + return this.data[index]; + } + + /** + * Get the number of scalars. + * + * @return the number of scalars + */ + public int size() { + return this.data.length; + } + + /** + * Convert this object to an LCSim {@link org.lcsim.event.GenericObject} for persistency to LCIO. + * + * @return the LCIO <code>GenericObject</code> containing scalar data + */ + GenericObject toGenericObject() { + final ScalarsGenericObject object = new ScalarsGenericObject(this.data); + return object; + } + + /** + * Convert this object to a readable string, which is a list of integer values enclosed in braces and separated by + * commas. + * + * @return this object converted to a string + */ + @Override public String toString() { - StringBuffer sb = new StringBuffer(); + final StringBuffer sb = new StringBuffer(); sb.append("["); - for (int value : data) { + for (final int value : this.data) { sb.append(value + ", "); } - sb.setLength(sb.length() - 2); + sb.setLength(sb.length() - 2); sb.append("]"); return sb.toString(); - } + } + + /** + * Write this object out to an LCIO event using the default collection name. + * + * @param event the output LCIO event + */ + public void write(final EventHeader event) { + write(event, DEFAULT_SCALAR_DATA_COLLECTION_NAME); + } + + /** + * Write this object out to an LCIO event using the given collection name. + * + * @param event the output LCIO event + * @param collectionName the name of the output collection + */ + public void write(final EventHeader event, final String collectionName) { + final List<GenericObject> collection = new ArrayList<GenericObject>(); + collection.add(toGenericObject()); + event.put(collectionName, collection, GenericObject.class, 0); + } } Modified: java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarUtilities.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarUtilities.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarUtilities.java Mon Apr 13 17:23:55 2015 @@ -3,88 +3,90 @@ /** * Utilities methods for scalar data. * <p> - * Currently this is used only for computing live time measurements from standard - * scalar data. - * - * @author Jeremy McCormick <[log in to unmask]> + * Currently this is used only for computing live time measurements from standard scalar data. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ -public class ScalarUtilities { - +public final class ScalarUtilities { + /** - * This class shouldn't be instantiated. - */ - private ScalarUtilities() { - } - - /** - * Indices for getting live time measurements. + * Indices for getting live time measurements. */ public enum LiveTimeIndex { - FCUP_TDC, /* Faraday cup TDC */ - FCUP_TRG, /* Faraday cup TRG */ - CLOCK; /* clock */ + CLOCK, /* Faraday cup TDC */ + FCUP_TDC, /* Faraday cup TRG */ + FCUP_TRG; /* clock */ } - + + /** + * Get a specific live time measurement by index. + * + * @param index The enum of the index type. + * @see LiveTimeIndex + */ + public static double getLiveTime(final ScalarData data, final LiveTimeIndex index) { + return getLiveTimes(data)[index.ordinal()]; + } + /** * Get the live time measurements from standard scalar data. * <p> * This is returned as a double array of size 3 containing:</br> + * * <pre> * [0] = FCUP TDC measurement * [1] = FCUP TRG measurement * [2] = CLOCK measurement * </pre> - * This method assumes the standard scalar data structure as outlined in - * <a href="https://jira.slac.stanford.edu/browse/HPSJAVA-470">HPSJAVA-470</a>. - * + * + * This method assumes the standard scalar data structure as outlined in <a + * href="https://jira.slac.stanford.edu/browse/HPSJAVA-470">HPSJAVA-470</a>. + * * @param data The scalar data. * @return The live time measurements. */ - public static double[] getLiveTimes(ScalarData data) { - + public static double[] getLiveTimes(final ScalarData data) { + // [03] - gated faraday cup with "TDC" threshold - int word03 = data.getValue(3); - + final int word03 = data.getValue(3); + // [19] - gated faraday cup with "TRG" threshold - int word19 = data.getValue(19); + final int word19 = data.getValue(19); // [35] - ungated faraday cup with "TDC" threshold - int word35 = data.getValue(35); - + final int word35 = data.getValue(35); + // [51] - ungated faraday cup with "TRG" threshold - int word51 = data.getValue(51); + final int word51 = data.getValue(51); // [67] - gated clock - int word67 = data.getValue(67); + final int word67 = data.getValue(67); // [68] - ungated clock - int word68 = data.getValue(68); - + final int word68 = data.getValue(68); + // [03]/[35] = FCUP TDC - double fcupTdc = (double) word03 / (double) word35; - + final double fcupTdc = (double) word03 / (double) word35; + // [19]/[51] = FCUP TRG - double fcupTrg = (double) word19 / (double) word51; - + final double fcupTrg = (double) word19 / (double) word51; + // [67]/[68] = CLOCK - double clock = (double) word67 / (double) word68; - + final double clock = (double) word67 / (double) word68; + // Compute the live times. - double[] liveTimes = new double[3]; + final double[] liveTimes = new double[3]; liveTimes[LiveTimeIndex.FCUP_TDC.ordinal()] = fcupTdc; liveTimes[LiveTimeIndex.FCUP_TRG.ordinal()] = fcupTrg; liveTimes[LiveTimeIndex.CLOCK.ordinal()] = clock; - + return liveTimes; } - + /** - * Get a specific live time measurement by index. - * @param index The enum of the index type. - * - * @see LiveTimeIndex + * Disallow class instantiation. */ - public static double getLiveTime(ScalarData data, LiveTimeIndex index) { - return getLiveTimes(data)[index.ordinal()]; + private ScalarUtilities() { + throw new UnsupportedOperationException("Do not instantiate this class."); } } Modified: java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarsEvioProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarsEvioProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarsEvioProcessor.java Mon Apr 13 17:23:55 2015 @@ -1,42 +1,47 @@ package org.hps.record.scalars; +import org.hps.record.evio.EvioEventConstants; import org.hps.record.evio.EvioEventProcessor; import org.jlab.coda.jevio.BaseStructure; import org.jlab.coda.jevio.EvioEvent; /** * This is an EVIO event processor for creating a {@link ScalarData} object from scalar bank data. - * - * @author Jeremy McCormick <[log in to unmask]> + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ -public class ScalarsEvioProcessor extends EvioEventProcessor { - - // Tag of the crate bank, which is a child of the top bank. - static final int SCALARS_CRATE_TAG = 39; - - // Tag of the scalars integer bank, which is a child of the crate bank. - static final int SCALARS_BANK_TAG = 57621; +public final class ScalarsEvioProcessor extends EvioEventProcessor { // Currently cached ScalarData object which was created by the process method. - ScalarData data; + private ScalarData data; /** - * This method will create a <code>ScalarData</code> object and cache it. - * The current object is first reset to null every time this is called. - * - * @param evio The EVIO event data. + * Get the current scalar data or null if there was none in the last event processed. + * + * @return the current scalar data or <code>null</code> if none exists */ - public void process(EvioEvent evio) { - data = null; - for (BaseStructure bank : evio.getChildrenList()) { + public ScalarData getScalarData() { + return this.data; + } + + /** + * This method will create a <code>ScalarData</code> object and cache it. The current object is first reset to + * <code>null</code> every time this method is called. + * + * @param evio the EVIO event data + */ + @Override + public void process(final EvioEvent evio) { + this.data = null; + for (final BaseStructure bank : evio.getChildrenList()) { // Does the crate tag match? - if (bank.getHeader().getTag() == SCALARS_CRATE_TAG) { + if (bank.getHeader().getTag() == EvioEventConstants.SCALARS_CRATE_TAG) { if (bank.getChildrenList() != null) { - for (BaseStructure subBank : bank.getChildrenList()) { + for (final BaseStructure subBank : bank.getChildrenList()) { // Does the bank tag match? - if (subBank.getHeader().getTag() == SCALARS_BANK_TAG) { + if (subBank.getHeader().getTag() == EvioEventConstants.SCALARS_BANK_TAG) { // Scalar data exists in event so create object and stop processing. - data = new ScalarData(subBank.getIntData()); + this.data = new ScalarData(subBank.getIntData()); break; } } @@ -44,12 +49,4 @@ } } } - - /** - * Get the current scalar data or null if there was none in the last event processed. - * @return The current scalar data or null if none exists. - */ - public ScalarData getScalarData() { - return data; - } } Modified: java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarsGenericObject.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarsGenericObject.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/scalars/ScalarsGenericObject.java Mon Apr 13 17:23:55 2015 @@ -3,25 +3,45 @@ import org.lcsim.event.GenericObject; /** - * This is the LCIO {@link org.lcsim.event.GenericObject} binding - * for EVIO scalar data. This should not be used directly. Rather - * the {@link ScalarData} class should be used for loading data - * from LCIO events. - * - * @author Jeremy McCormick <[log in to unmask]> + * This is the LCIO {@link org.lcsim.event.GenericObject} binding for EVIO scalar data. This should not be used + * directly. Rather the {@link ScalarData} class should be used for loading data from LCIO events. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> */ final class ScalarsGenericObject implements GenericObject { - int[] values; + /** + * The scalar data values. + */ + private final int[] values; - @Override - public int getNInt() { - return values.length; + /** + * Create a new object with the given scalar values. + * + * @param values the array of scalar values + */ + ScalarsGenericObject(final int[] values) { + this.values = values; } @Override - public int getNFloat() { + public double getDoubleVal(final int index) { return 0; + } + + @Override + public float getFloatVal(final int index) { + return 0; + } + + /** + * Get the scalar value at the index. + * + * @param index the index in the data array + */ + @Override + public int getIntVal(final int index) { + return this.values[index]; } @Override @@ -30,20 +50,25 @@ } @Override - public int getIntVal(int index) { - return values[index]; - } - - @Override - public float getFloatVal(int index) { + public int getNFloat() { return 0; } + /** + * Get the number of integer values in the array. + * + * @return the number of integer values in the array + */ @Override - public double getDoubleVal(int index) { - return 0; + public int getNInt() { + return this.values.length; } + /** + * Returns <code>false</code> to indicate object is not fixed size. + * + * @return <code>false</code> to indicate object is not fixed size + */ @Override public boolean isFixedSize() { return false; Added: java/trunk/record-util/src/main/java/org/hps/record/scalars/package-info.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/scalars/package-info.java (added) +++ java/trunk/record-util/src/main/java/org/hps/record/scalars/package-info.java Mon Apr 13 17:23:55 2015 @@ -0,0 +1,6 @@ +/** + * Classes for converting scalar data from EVIO to LCSim. + * + * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a> + */ +package org.hps.record.scalars;