blob: 053a0b2461db66a3ccf94795759bbcb66092688a [file] [log] [blame]
/********************************************************************************
* Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
package org.eclipse.mdm.openatfx.mdf.mdf4;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.SeekableByteChannel;
import java.util.Arrays;
/**
* <p>
* THE EVENT BLOCK <code>EVBLOCK<code>
* </p>
* The EVBLOCK stored Data about an event, that influenced the measurement, e.g.
* start, end, errors...
*
* @author Tobias Leemann
*/
class EVBLOCK extends BLOCK {
public static String BLOCK_ID = "##EV";
/** Link section */
// Pointer to next event block (EVBLOCK) (can be NIL)
// LINK
private long lnkEvNext;
// Pointer to parent EVBLOCK (can be NIL)
// LINK
private long lnkEvParent;
// Pointer to event block which defines the beginning of a range (EVBLOCK)
// (can be NIL)
// LINK
private long lnkEvRange;
// Pointer to TextBlock with EventName (can be NIL)
// LINK
private long lnkTxName;
// Pointer to comment and additional information (TXBLOCK or MDBLOCK) (can
// be NIL)
// LINK
private long lnkMdComment;
// Pointers to Blocks affected by this event. (CNBLOCK or CGBLOCK) (can be
// NIL)
// LINK
private long[] lnkScope;
// Pointers to Referenced Attachment Blocks (ATBLOCK) (can be NIL)
// LINK
private long[] lnkAtReference;
/** Data section */
// Event Type
// 0 = Recording
// 1 = Recording Interrupt
// 2 = Acquisition Interrupt
// 3 = Start Recording Trigger
// 4 = Stop Recording Trigger
// 5 = Trigger
// 6 = Marker
// UINT8
private byte type;
private byte syncType;
// Range Type
// 0 = Point
// 1 = Beginning of Range
// 2 = End of Ranger
// UINT8
private byte rangeType;
// Event Cause
// 0 = OTHER
// 1 = ERROR
// 2 = TOOL
// 3 = SCRIPT
// 4 = USER
// UINT8
private byte cause;
// Flags
// Bit 0 = PostProcessingFlag
// UINT8
private byte flags;
/**
* Number of Scope Links
*/
private long scopeCount;
/**
* Number of Attachments
*/
private int attachmentCount;
/**
* Number of FH-Block in list, specifying the tool responsible for this
* event.
*/
private int creatorIndex;
/**
* Base for sync value.
*/
private long syncBaseValue;
/**
* Factor for sync value.
*/
private double syncFactor;
/**
* Constructor.
*
* @param sbc
* The byte channel pointing to the MDF file.
* @param pos
* The position of the block within the MDF file.
*/
private EVBLOCK(SeekableByteChannel sbc, long pos) {
super(sbc, pos);
}
public static String getBLOCK_ID() {
return BLOCK_ID;
}
public long getLnkEvNext() {
return lnkEvNext;
}
public long getLnkEvParent() {
return lnkEvParent;
}
public long getLnkEvRange() {
return lnkEvRange;
}
public long getLnkTxName() {
return lnkTxName;
}
public long getLnkMdComment() {
return lnkMdComment;
}
public long[] getLnkScope() {
return lnkScope;
}
public long[] getLnkAtReference() {
return lnkAtReference;
}
public byte getType() {
return type;
}
public byte getSyncType() {
return syncType;
}
public byte getRangeType() {
return rangeType;
}
public byte getCause() {
return cause;
}
public byte getFlags() {
return flags;
}
public long getScopeCount() {
return scopeCount;
}
public int getAttachmentCount() {
return attachmentCount;
}
public int getCreatorIndex() {
return creatorIndex;
}
public long getSyncBaseValue() {
return syncBaseValue;
}
public double getSyncFactor() {
return syncFactor;
}
private void setLnkEvNext(long lnkEvNext) {
this.lnkEvNext = lnkEvNext;
}
private void setLnkEvParent(long lnkEvParent) {
this.lnkEvParent = lnkEvParent;
}
private void setLnkEvRange(long lnkEvRange) {
this.lnkEvRange = lnkEvRange;
}
private void setLnkTxName(long lnkTxName) {
this.lnkTxName = lnkTxName;
}
private void setLnkMdComment(long lnkMdComment) {
this.lnkMdComment = lnkMdComment;
}
private void setLnkScope(long[] lnkScope) {
this.lnkScope = lnkScope;
}
private void setLnkAtReference(long[] lnkAtReference) {
this.lnkAtReference = lnkAtReference;
}
private void setType(byte type) {
this.type = type;
}
private void setSyncType(byte syncType) {
this.syncType = syncType;
}
private void setRangeType(byte rangeType) {
this.rangeType = rangeType;
}
private void setCause(byte cause) {
this.cause = cause;
}
private void setFlags(byte flags) {
this.flags = flags;
}
private void setScopeCount(long scopeCount) {
this.scopeCount = scopeCount;
}
private void setAttachmentCount(int attachmentCount) {
this.attachmentCount = attachmentCount;
}
private void setCreatorIndex(int creatorIndex) {
this.creatorIndex = creatorIndex;
}
private void setSyncBaseValue(long syncBaseValue) {
this.syncBaseValue = syncBaseValue;
}
private void setSyncFactor(double syncFactor) {
this.syncFactor = syncFactor;
}
public double getSyncValue() {
return syncBaseValue * syncFactor;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "EVBLOCK [lnkEvNext=" + lnkEvNext + ", lnkEvParent=" + lnkEvParent + ", lnkEvRange=" + lnkEvRange
+ ", lnkTxName=" + lnkTxName + ", lnkMdComment=" + lnkMdComment + ", lnkScope="
+ Arrays.toString(lnkScope) + ", lnkAtReference=" + Arrays.toString(lnkAtReference) + ", type=" + type
+ ", syncType=" + syncType + ", rangeType=" + rangeType + ", cause=" + cause + ", flags=" + flags
+ ", scopeCount=" + scopeCount + ", attachmentCount=" + attachmentCount + ", creatorIndex="
+ creatorIndex + ", syncBaseBValue=" + syncBaseValue + ", syncFactor=" + syncFactor + "]";
}
public EVBLOCK getEvNextBlock() throws IOException {
if (lnkEvNext > 0) {
return EVBLOCK.read(sbc, lnkEvNext);
}
return null;
}
public BLOCK getMdCommentBlock() throws IOException {
if (lnkMdComment > 0) {
String blockType = getBlockType(sbc, lnkMdComment);
// link points to a MDBLOCK
if (blockType.equals(MDBLOCK.BLOCK_ID)) {
return MDBLOCK.read(sbc, lnkMdComment);
}
// links points to TXBLOCK
else if (blockType.equals(TXBLOCK.BLOCK_ID)) {
return TXBLOCK.read(sbc, lnkMdComment);
}
// unknown
else {
throw new IOException("Unsupported block type for MdComment: " + blockType);
}
}
return null;
}
public TXBLOCK getEvTxNameBlock() throws IOException {
if (lnkTxName > 0) {
return TXBLOCK.read(sbc, lnkTxName);
}
return null;
}
/**
* Reads an EVBLOCK from the channel.
*
* @param channel
* The channel to read from.
* @param pos
* The position within the channel.
* @return The block data.
* @throws IOException
* The exception.
*/
public static EVBLOCK read(SeekableByteChannel channel, long pos) throws IOException {
EVBLOCK block = new EVBLOCK(channel, pos);
// read block header
ByteBuffer bb = ByteBuffer.allocate(24);
bb.order(ByteOrder.LITTLE_ENDIAN);
channel.position(pos);
channel.read(bb);
bb.rewind();
// CHAR 4: Block type identifier
block.setId(MDF4Util.readCharsISO8859(bb, 4));
if (!block.getId().equals(BLOCK_ID)) {
throw new IOException("Wrong block type - expected '" + BLOCK_ID + "', found '" + block.getId() + "'");
}
// BYTE 4: Reserved used for 8-Byte alignment
bb.get(new byte[4]);
// UINT64: Length of block
block.setLength(MDF4Util.readUInt64(bb));
// UINT64: Number of links
block.setLinkCount(MDF4Util.readUInt64(bb));
// Read link section
bb = ByteBuffer.allocate((int) (8 * block.getLinkCount()));
bb.order(ByteOrder.LITTLE_ENDIAN);
channel.read(bb);
bb.rewind();
// LINK: Pointer to next EVBLOCK (can be NIL)
block.setLnkEvNext(MDF4Util.readLink(bb));
// LINK: Pointer to Parent EVBLOCK (can be NIL)
block.setLnkEvParent(MDF4Util.readLink(bb));
// LINK: Pointer to Range limit EVBLOCK (can be NIL)
block.setLnkEvRange(MDF4Util.readLink(bb));
// LINK: Pointer to name block TXBLOCK
block.setLnkTxName(MDF4Util.readLink(bb));
// LINK: Pointer to comment and additional information (TXBLOCK or
// MDBLOCK) (can be NIL)
block.setLnkMdComment(MDF4Util.readLink(bb));
// Read remaining links
long[] remaining = new long[(int) (block.getLinkCount() - 5)];
for (int i = 0; i < block.getLinkCount() - 5; i++) {
remaining[i] = MDF4Util.readLink(bb);
}
// Read data section
bb = ByteBuffer.allocate(32);
bb.order(ByteOrder.LITTLE_ENDIAN);
channel.read(bb);
bb.rewind();
// UINT8: Type
block.setType(MDF4Util.readUInt8(bb));
// UINT8: SyncType
block.setSyncType(MDF4Util.readUInt8(bb));
// UINT8: RangeType
block.setRangeType(MDF4Util.readUInt8(bb));
// UINT8: Cause
block.setCause(MDF4Util.readUInt8(bb));
// UINT8: Flags
block.setFlags(MDF4Util.readUInt8(bb));
// Skip 3 Byte
bb.get(new byte[3]);
// UINT32: Scope List
block.setScopeCount(MDF4Util.readUInt32(bb));
long[] scopel = new long[(int) block.getScopeCount()];
System.arraycopy(remaining, 0, scopel, 0, (int) block.getScopeCount());
block.setLnkScope(scopel);
// UINT16: Attachment count
block.setAttachmentCount(MDF4Util.readUInt16(bb));
long[] attmt = new long[block.getAttachmentCount()];
System.arraycopy(remaining, (int) block.getScopeCount(), attmt, 0, block.getAttachmentCount());
block.setLnkAtReference(attmt);
// UINT16: Creator index
block.setCreatorIndex(MDF4Util.readUInt16(bb));
// UINT64: Sync Base
block.setSyncBaseValue(MDF4Util.readUInt64(bb));
// REAL: Sync Factor
block.setSyncFactor(MDF4Util.readReal(bb));
return block;
}
}