Java tutorial
/** * Copyright: 2007 Regents of the University of Hawaii and the * School of Ocean and Earth Science and Technology * Purpose: A class that represents the ensemble header of data produced by * an RDI 1200kHz Workhorse Acoustic Doppler Current Profiler in the * default PD0 format as described in RDI's "Workhorse Commands and * Output Data Format" manual, P/N 957-6156-00 (March 2005) * Authors: Christopher Jones * * $HeadURL$ * $LastChangedDate$ * $LastChangedBy$ * $LastChangedRevision$ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package edu.hawaii.soest.kilonalu.adcp; import java.nio.ByteBuffer; import java.nio.ByteOrder; import org.apache.commons.codec.binary.Hex; /** * A class that represents the ensemble header of data produced by * an RDI 1200kHz Workhorse Acoustic Doppler Current Profiler in the * default PD0 format. */ public class EnsembleHeader { /** * A field that stores the Ensemble Data Source ID (one byte) in a ByteBuffer */ private ByteBuffer dataSourceID = ByteBuffer.allocate(1); /** * A field that stores the binary byte address offsets where data types * 1 to n are stored (in a ByteBuffer). Each address offset is * represented by a 2-byte sequence. For instance, the offset for * Data Type #1 (FixedLeader) is the first two bytes of this ByteBuffer. * These two bytes are in Little Endian order, and must be read as such. * Add 1 to this address location to get the binary byte location of the * beginning of Data Type #1 (FixedLeader). Repeat this to read * Data Type #2 (VariableLeader), Data Type #3 (VelocityProfile), etc... */ private ByteBuffer dataTypeOffsets; /** * A field that stores the default Ensemble Header ID ( 0x7F7F) */ private static final ByteBuffer DEFAULT_HEADER_ID = ByteBuffer.wrap(new byte[] { 0x7F, 0x7F }); /** * A field that stores the Ensemble Header ID (2-bytes) in a ByteBuffer */ private ByteBuffer headerID = DEFAULT_HEADER_ID; /** * A field that stores the Ensemble Header Spare (one byte) in a ByteBuffer * This field is reserved for RDI internal use. */ private ByteBuffer headerSpare = ByteBuffer.allocate(1); /** * A field that stores the number of bytes from the start of the * current ensemble up to, but not including, the 2-byte checksum, in a * ByteBuffer that has Little Endian order (same as the data stream) */ private ByteBuffer numberOfBytesInEnsemble = ByteBuffer.allocate(2); /** * A field that stores the number of data types selected for collection. */ private ByteBuffer numberOfDataTypes = ByteBuffer.allocate(1); /** * Constructor. This method populates the Header fields from the given * ByteBuffer of data passed in as an argument. * * @param ensembleBuffer the ByteBuffer that contains the binary ensemble data */ public EnsembleHeader(ByteBuffer ensembleBuffer, Ensemble ensemble) { // prepare the ensemble buffer for reading ensembleBuffer.flip(); // define the temporary arrays for passing bytes byte[] oneByte = new byte[1]; byte[] twoBytes = new byte[2]; // set each of the Ensemble Header fields n the order that they are // read from the byte stream ensembleBuffer.get(twoBytes); setHeaderID(twoBytes); headerID.flip(); ensemble.addToByteSum(twoBytes); ensembleBuffer.get(twoBytes); setNumberOfBytesInEnsemble(twoBytes); numberOfBytesInEnsemble.flip(); ensemble.addToByteSum(twoBytes); ensembleBuffer.get(oneByte); setHeaderSpare(oneByte); headerSpare.flip(); ensemble.addToByteSum(oneByte); ensembleBuffer.get(oneByte); setNumberOfDataTypes(oneByte); numberOfDataTypes.flip(); ensemble.addToByteSum(oneByte); // set the dataTypeOffsets ByteBuffer size dataTypeOffsets = ByteBuffer.allocate(((int) getNumberOfDataTypes().get()) * 2); numberOfDataTypes.flip(); byte[] offsetBytes = new byte[(getNumberOfDataTypes().get() * 2)]; numberOfDataTypes.flip(); ensembleBuffer.get(offsetBytes); setDataTypeOffsets(offsetBytes); dataTypeOffsets.flip(); ensemble.addToByteSum(offsetBytes); } /** * A method that returns the Ensemble headerID field contents * as a ByteBuffer. */ protected ByteBuffer getHeaderID() { this.headerID.limit(this.headerID.capacity()); this.headerID.position(0); return this.headerID; } /** * A method that returns the Ensemble headerSpare field contents * as a ByteBuffer. */ protected ByteBuffer getHeaderSpare() { this.headerSpare.limit(this.headerSpare.capacity()); this.headerSpare.position(0); return this.headerSpare; } /** * A method that returns the offset for the given Data Type number. * For instance, The offset for Data Type #1 (FixedLeader) will be returned * by calling this method with a dataTypeNumber argument of 1. * * @param dataTypeNumber the number of the Data Type desired (as a ByteBuffer) */ protected ByteBuffer getDataTypeOffset(int dataTypeNumber) { // prepare the ByteBuffer for reading this.dataTypeOffsets.limit(this.dataTypeOffsets.capacity()); // read the offset by setting the position based on the desired type dataTypeOffsets.position(((dataTypeNumber * 2) - 2)); byte[] offsetBytes = new byte[2]; ByteBuffer dataTypeOffset = dataTypeOffsets.get(offsetBytes); dataTypeOffset.position(dataTypeOffset.position() - 2); return dataTypeOffset; } /** * A method that returns the numberOfBytesInEnsemble field contents * as a ByteBuffer. */ protected ByteBuffer getNumberOfBytesInEnsemble() { this.numberOfBytesInEnsemble.limit(this.numberOfBytesInEnsemble.capacity()); this.numberOfBytesInEnsemble.position(0); return this.numberOfBytesInEnsemble; } /** * A method that returns the numberOfDataTypes field contents * as a ByteBuffer. */ protected ByteBuffer getNumberOfDataTypes() { this.numberOfDataTypes.limit(this.numberOfDataTypes.capacity()); this.numberOfDataTypes.position(0); return this.numberOfDataTypes; } /** * A method that sets the dataTypesOffsets field from the given * byte array. The byteArray argument must be equal to the numberOfDataTypes * field times 2 (since each offset takes 2 bytes). * * @param byteArray the 2-byte array that contains the header ID */ private void setDataTypeOffsets(byte[] byteArray) { this.dataTypeOffsets.put(byteArray); } /** * A method that sets the Ensemble Header ID field from the given * byte array. The byteArray argument must be 2 bytes in size. * * @param byteArray the 2-byte array that contains the header ID */ private void setHeaderID(byte[] byteArray) { this.headerID.put(byteArray); } /** * A method that sets the Header Spare field from the given * byte array. The byteArray argument must be 1 bytes in size. * * @param byteArray the 1-byte array that contains the header spare */ private void setHeaderSpare(byte[] byteArray) { this.headerSpare.put(byteArray); } /** * A method that sets the numberOfBytesInEnsemble field from the given * byte array. The byteArray argument must be 2-bytes in size. * * @param byteArray the 2-byte byte array that contains the header bytes */ private void setNumberOfBytesInEnsemble(byte[] byteArray) { this.numberOfBytesInEnsemble.put(byteArray); } /** * A method that sets the numberOfDataTypes field from the given * byte array. The byteArray argument must be 1-byte in size. * * @param byteArray the 1-byte byte array that contains the header bytes */ private void setNumberOfDataTypes(byte[] byteArray) { this.numberOfDataTypes.put(byteArray); } }