/*
* Licensed under the Apache License, Version 2.0 (the "License");
*
* You may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributions from 2013-2017 where performed either by US government
* employees, or under US Veterans Health Administration contracts.
*
* US Veterans Health Administration contributions by government employees
* are work of the U.S. Government and are not subject to copyright
* protection in the United States. Portions contributed by government
* employees are USGovWork (17USC ยง105). Not subject to copyright.
*
* Contribution by contractors to the US Veterans Health Administration
* during this period are contractually contributed under the
* Apache License, Version 2.0.
*
* See: https://www.usa.gov/government-works
*
* Contributions prior to 2013:
*
* Copyright (C) International Health Terminology Standards Development Organisation.
* Licensed under the Apache License, Version 2.0.
*
*/
package sh.isaac.api.externalizable;
//~--- JDK imports ------------------------------------------------------------
import java.io.UTFDataFormatException;
import java.nio.ReadOnlyBufferException;
import java.util.Arrays;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.locks.StampedLock;
import javax.xml.bind.DatatypeConverter;
//~--- non-JDK imports --------------------------------------------------------
import sh.isaac.api.Get;
import sh.isaac.api.IdentifierService;
import sh.isaac.api.commit.StampService;
//~--- classes ----------------------------------------------------------------
/**
* The Class ByteArrayDataBuffer.
*
* @author kec
*/
public class ByteArrayDataBuffer {
/** The Constant MAX_DATA_SIZE. */
private static final int MAX_DATA_SIZE = Integer.MAX_VALUE - 16;
/** The Constant DEFAULT_SIZE. */
private static final int DEFAULT_SIZE = 1024;
/** The Constant FALSE. */
protected static final byte FALSE = 0;
/** The Constant TRUE. */
protected static final byte TRUE = 1;
//~--- fields --------------------------------------------------------------
/** The position. */
protected int position = 0;
/** The read only. */
protected boolean readOnly = false;
/** The object data format version. */
protected byte objectDataFormatVersion = 0;
/** The external data. */
protected boolean externalData = false;
/**
* The StampedLock is to ensure the backing array does not grow underneath a
* concurrent operation. The locks do not prevent concurrent threads from
* reading or writing to the same fields.
*/
protected final StampedLock sl = new StampedLock();
/** The used. */
protected int used = 0;
/** The position start. */
protected final int positionStart;
/** The identifier service. */
protected IdentifierService identifierService;
/** The stamp service. */
protected StampService stampService;
/** The data. */
private byte[] data;
//~--- constructors --------------------------------------------------------
/**
* Instantiates a new byte array data buffer.
*/
public ByteArrayDataBuffer() {
this(DEFAULT_SIZE);
}
/**
* Instantiates a new byte array data buffer.
*
* @param data the data
*/
public ByteArrayDataBuffer(byte[] data) {
this(data, 0);
}
/**
* Instantiates a new byte array data buffer.
*
* @param size the size
*/
public ByteArrayDataBuffer(int size) {
this.data = new byte[size];
this.positionStart = 0;
}
/**
* Instantiates a new byte array data buffer.
*
* @param data the data
* @param positionStart the position start
*/
public ByteArrayDataBuffer(byte[] data, int positionStart) {
this.data = data;
this.used = data.length;
this.positionStart = positionStart;
}
//~--- methods -------------------------------------------------------------
/**
* Append.
*
* @param db the db
* @param position the position
* @param length the length
*/
public void append(ByteArrayDataBuffer db, int position, int length) {
ensureSpace(this.position + length);
System.arraycopy(db.data, position, this.data, this.position, length);
this.position += length;
}
/**
* Makes this buffer ready for a new sequence of put operations:
* It sets the limit to positionStart, and the position to positionStart.
*
* @return the byte array data buffer
*/
public ByteArrayDataBuffer clear() {
this.used = 0;
this.position = this.positionStart;
return this;
}
/**
* Makes this buffer ready for a new sequence of get operations:
* It sets the limit to the current position and then sets the position to zero.
*
* @return the byte array data buffer
*/
public ByteArrayDataBuffer flip() {
getLimit();
this.position = this.positionStart;
return this;
}
/**
* New wrapper.
*
* @return the byte array data buffer
*/
public ByteArrayDataBuffer newWrapper() {
final ByteArrayDataBuffer newWrapper = new ByteArrayDataBuffer(this.data);
newWrapper.readOnly = true;
newWrapper.position = 0;
newWrapper.used = this.used;
return newWrapper;
}
/**
* Put.
*
* @param src the src
*/
public void put(byte[] src) {
put(src, 0, src.length);
}
/**
* Put.
*
* @param src the src
* @param offset the offset
* @param length the length
*/
public void put(byte[] src, int offset, int length) {
ensureSpace(this.position + length);
long lockStamp = this.sl.tryOptimisticRead();
System.arraycopy(src, offset, this.data, this.position, length);
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
System.arraycopy(src, offset, this.data, this.position, length);
} finally {
this.sl.unlockRead(lockStamp);
}
}
this.position += length;
}
/**
* Put boolean.
*
* @param x the x
*/
public void putBoolean(boolean x) {
if (x) {
putByte(TRUE);
} else {
putByte(FALSE);
}
}
/**
* Put byte.
*
* @param x the x
*/
public void putByte(byte x) {
ensureSpace(this.position + 1);
long lockStamp = this.sl.tryOptimisticRead();
this.data[this.position] = x;
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
this.data[this.position] = x;
} finally {
this.sl.unlockRead(lockStamp);
}
}
this.position += 1;
}
/**
* Put byte array field.
*
* @param array the array
*/
public void putByteArrayField(byte[] array) {
putInt(array.length);
put(array, 0, array.length);
}
/**
* Put char.
*
* @param x the x
*/
public void putChar(char x) {
putShort((short) x);
}
/**
* Put concept sequence.
*
* @param conceptSequence the concept sequence
*/
public void putConceptSequence(int conceptSequence) {
if (this.externalData) {
final UUID uuid =
this.identifierService.getUuidPrimordialForNid(this.identifierService.getConceptNid(conceptSequence))
.get();
putLong(uuid.getMostSignificantBits());
putLong(uuid.getLeastSignificantBits());
} else {
putInt(conceptSequence);
}
}
/**
* Put double.
*
* @param d the d
*/
public void putDouble(double d) {
putLong(Double.doubleToLongBits(d));
}
/**
* Put float.
*
* @param f the f
*/
public void putFloat(float f) {
putInt(Float.floatToRawIntBits(f));
}
/**
* Put int.
*
* @param x the x
*/
public void putInt(int x) {
ensureSpace(this.position + 4);
long lockStamp = this.sl.tryOptimisticRead();
this.data[this.position] = (byte) (x >> 24);
this.data[this.position + 1] = (byte) (x >> 16);
this.data[this.position + 2] = (byte) (x >> 8);
this.data[this.position + 3] = (byte) (x);
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
this.data[this.position] = (byte) (x >> 24);
this.data[this.position + 1] = (byte) (x >> 16);
this.data[this.position + 2] = (byte) (x >> 8);
this.data[this.position + 3] = (byte) (x);
} finally {
this.sl.unlockRead(lockStamp);
}
}
this.position += 4;
}
/**
* Put int array.
*
* @param src the src
*/
public void putIntArray(int[] src) {
putInt(src.length);
ensureSpace(this.position + (src.length * 4));
long lockStamp = this.sl.tryOptimisticRead();
final int startingPosition = this.position;
putIntArrayIntoData(src);
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
this.position = startingPosition;
try {
putIntArrayIntoData(src);
} finally {
this.sl.unlockRead(lockStamp);
}
}
}
/**
* Put long.
*
* @param x the x
*/
public void putLong(long x) {
ensureSpace(this.position + 8);
long lockStamp = this.sl.tryOptimisticRead();
this.data[this.position] = (byte) (x >> 56);
this.data[this.position + 1] = (byte) (x >> 48);
this.data[this.position + 2] = (byte) (x >> 40);
this.data[this.position + 3] = (byte) (x >> 32);
this.data[this.position + 4] = (byte) (x >> 24);
this.data[this.position + 5] = (byte) (x >> 16);
this.data[this.position + 6] = (byte) (x >> 8);
this.data[this.position + 7] = (byte) (x);
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
this.data[this.position] = (byte) (x >> 56);
this.data[this.position + 1] = (byte) (x >> 48);
this.data[this.position + 2] = (byte) (x >> 40);
this.data[this.position + 3] = (byte) (x >> 32);
this.data[this.position + 4] = (byte) (x >> 24);
this.data[this.position + 5] = (byte) (x >> 16);
this.data[this.position + 6] = (byte) (x >> 8);
this.data[this.position + 7] = (byte) (x);
} finally {
this.sl.unlockRead(lockStamp);
}
}
this.position += 8;
}
/**
* Put nid.
*
* @param nid the nid
*/
public void putNid(int nid) {
if (this.externalData) {
final Optional<UUID> optionalUuid = this.identifierService.getUuidPrimordialForNid(nid);
if (optionalUuid.isPresent()) {
final UUID uuid = optionalUuid.get();
putLong(uuid.getMostSignificantBits());
putLong(uuid.getLeastSignificantBits());
} else {
throw new RuntimeException("Can't find uuid for nid: " + nid);
}
} else {
putInt(nid);
}
}
/**
* Put sememe sequence.
*
* @param sememeSequence the sememe sequence
*/
public void putSememeSequence(int sememeSequence) {
if (this.externalData) {
final UUID uuid =
this.identifierService.getUuidPrimordialForNid(this.identifierService.getSememeNid(sememeSequence))
.get();
putLong(uuid.getMostSignificantBits());
putLong(uuid.getLeastSignificantBits());
} else {
putInt(sememeSequence);
}
}
/**
* Put short.
*
* @param x the x
*/
public void putShort(short x) {
ensureSpace(this.position + 2);
long lockStamp = this.sl.tryOptimisticRead();
this.data[this.position] = (byte) (x >> 8);
this.data[this.position + 1] = (byte) (x);
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
this.data[this.position] = (byte) (x >> 8);
this.data[this.position + 1] = (byte) (x);
} finally {
this.sl.unlockRead(lockStamp);
}
}
this.position += 2;
}
/**
* Put stamp sequence.
*
* @param stampSequence the stamp sequence
*/
public void putStampSequence(int stampSequence) {
if (this.externalData) {
StampUniversal.get(stampSequence)
.writeExternal(this);
} else {
putInt(stampSequence);
}
}
/**
* Put UTF.
*
* @param str the str
*/
public void putUTF(String str) {
final int strlen = str.length();
int utflen = 0;
int c;
int count = 0;
for (int i = 0; i < strlen; i++) {
c = str.charAt(i);
if ((c >= 1) && (c <= 127)) {
utflen++;
} else if (c > 2047) {
utflen += 3;
} else {
utflen += 2;
}
}
final byte[] bytearr = new byte[utflen];
int i = 0;
for (; i < strlen; i++) {
c = str.charAt(i);
if (!((c >= 1) && (c <= 127))) {
break;
}
bytearr[count++] = (byte) c;
}
for (; i < strlen; i++) {
c = str.charAt(i);
if ((c >= 1) && (c <= 127)) {
bytearr[count++] = (byte) c;
} else if (c > 2047) {
bytearr[count++] = (byte) (224 | ((c >> 12) & 15));
bytearr[count++] = (byte) (128 | ((c >> 6) & 63));
bytearr[count++] = (byte) (128 | (c & 63));
} else {
bytearr[count++] = (byte) (192 | ((c >> 6) & 31));
bytearr[count++] = (byte) (128 | (c & 63));
}
}
putInt(utflen);
put(bytearr, 0, utflen);
}
/**
* Put uuid.
*
* @param uuid the uuid
*/
public void putUuid(UUID uuid) {
putLong(uuid.getMostSignificantBits());
putLong(uuid.getLeastSignificantBits());
}
/**
* Read UTF.
*
* @return the string
*/
public final String readUTF() {
final int[] positionArray = new int[] { this.position };
final String result = readUTF(positionArray);
this.position = positionArray[0];
return result;
}
/**
* Read UTF.
*
* @param position the position
* @return the string
*/
public final String readUTF(int[] position) {
final int utflen = getInt(position[0]);
final byte[] bytearr = new byte[utflen];
final char[] chararr = new char[utflen];
int c, char2, char3;
int count = 0;
int chararr_count = 0;
get(position[0] + 4, bytearr, 0, utflen);
position[0] = position[0] + 4 + utflen;
while (count < utflen) {
c = bytearr[count] & 0xff;
if (c > 127) {
break;
}
count++;
chararr[chararr_count++] = (char) c;
}
while (count < utflen) {
try {
c = bytearr[count] & 0xff;
switch (c >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
/* 0xxxxxxx */
count++;
chararr[chararr_count++] = (char) c;
break;
case 12:
case 13:
/* 110x xxxx 10xx xxxx */
count += 2;
if (count > utflen) {
throw new UTFDataFormatException("malformed input: partial character at end");
}
char2 = bytearr[count - 1];
if ((char2 & 0xC0) != 0x80) {
throw new UTFDataFormatException("malformed input around byte " + count);
}
chararr[chararr_count++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
/* 1110 xxxx 10xx xxxx 10xx xxxx */
count += 3;
if (count > utflen) {
throw new UTFDataFormatException("malformed input: partial character at end");
}
char2 = bytearr[count - 2];
char3 = bytearr[count - 1];
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
throw new UTFDataFormatException("malformed input around byte " + (count - 1));
}
chararr[chararr_count++] = (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | (char3 & 0x3F));
break;
default:
/* 10xx xxxx, 1111 xxxx */
throw new UTFDataFormatException("malformed input around byte " + count);
}
} catch (final UTFDataFormatException ex) {
throw new RuntimeException(ex);
}
}
// The number of chars produced may be less than utflen
return new String(chararr, 0, chararr_count);
}
/**
* Makes this buffer ready for re-reading the data that it already contains:
* It leaves the limit unchanged and sets the position to the positionStart.
*
* @return the byte array data buffer
*/
public ByteArrayDataBuffer rewind() {
this.position = this.positionStart;
return this;
}
/**
* Slice.
*
* @return the byte array data buffer
*/
public ByteArrayDataBuffer slice() {
final ByteArrayDataBuffer slice = new ByteArrayDataBuffer(this.data, this.position);
slice.readOnly = true;
slice.position = this.position;
slice.used = this.used;
return slice;
}
/**
* To string.
*
* @return the string
*/
@Override
public String toString() {
return "ByteArrayDataBuffer{" + "position=" + this.position + ", positionStart=" + this.positionStart +
", readOnly=" + this.readOnly + ", objectDataFormatVersion=" + this.objectDataFormatVersion +
", externalData=" + this.externalData + ", used=" + this.used + ", data=" +
DatatypeConverter.printHexBinary(this.data) + '}';
}
/**
* Trim to size.
*/
public void trimToSize() {
if (this.readOnly) {
throw new ReadOnlyBufferException();
}
final long lockStamp = this.sl.writeLock();
try {
if ((this.position < this.data.length) && (this.used < this.data.length)) {
final int newSize = Math.max(this.position, this.used);
final byte[] newData = new byte[newSize];
System.arraycopy(this.data, 0, newData, 0, newSize);
this.data = newData;
}
} finally {
this.sl.unlockWrite(lockStamp);
}
}
/**
* Ensure space.
*
* @param minSpace the min space
*/
private void ensureSpace(int minSpace) {
if (this.readOnly) {
throw new ReadOnlyBufferException();
}
if (minSpace > this.data.length) {
final long lockStamp = this.sl.writeLock();
try {
while (minSpace > this.data.length) {
int newCapacity = this.data.length << 1;
if (newCapacity > MAX_DATA_SIZE) {
newCapacity = MAX_DATA_SIZE;
}
this.data = Arrays.copyOf(this.data, newCapacity);
}
} finally {
this.sl.unlockWrite(lockStamp);
}
}
}
/**
* Put int array into data.
*
* @param src the src
*/
private void putIntArrayIntoData(int[] src) {
for (final int anInt: src) {
this.data[this.position] = (byte) (anInt >> 24);
this.data[this.position + 1] = (byte) (anInt >> 16);
this.data[this.position + 2] = (byte) (anInt >> 8);
this.data[this.position + 3] = (byte) (anInt);
this.position += 4;
}
}
//~--- get methods ---------------------------------------------------------
/**
* Gets the boolean.
*
* @return the boolean
*/
public boolean getBoolean() {
return getByte() != FALSE;
}
/**
* Gets the boolean.
*
* @param position the position
* @return the boolean
*/
public boolean getBoolean(int position) {
return getByte(position) != FALSE;
}
/**
* Gets the byte.
*
* @return the byte
*/
public byte getByte() {
final byte result = getByte(this.position);
this.position += 1;
return result;
}
/**
* Gets the byte.
*
* @param position the position
* @return the byte
*/
public byte getByte(int position) {
long lockStamp = this.sl.tryOptimisticRead();
byte result = this.data[position];
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
result = this.data[position];
} finally {
this.sl.unlockRead(lockStamp);
}
}
return result;
}
/**
* Gets the byte array field.
*
* @return a byte[] written to the ByteArrayDataBuffer. Does not return the entire
* data buffer as an array.
*/
public byte[] getByteArrayField() {
final int length = getInt();
long lockStamp = this.sl.tryOptimisticRead();
final byte[] results = new byte[length];
System.arraycopy(this.data, this.position, results, 0, length);
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
System.arraycopy(this.data, this.position, results, 0, length);
} finally {
this.sl.unlockRead(lockStamp);
}
}
this.position += length;
return results;
}
/**
* The current capacity of the buffer. The buffer will grow if necessary, so the current capacity may not
* reflect the maximum size that the buffer may obtain.
* @return The currently allocated size of the buffer.
*/
public int getCapacity() {
return this.data.length;
}
/**
* Gets the char.
*
* @return the char
*/
public char getChar() {
final char result = getChar(this.position);
this.position += 2;
return result;
}
/**
* Gets the char.
*
* @param position the position
* @return the char
*/
public char getChar(int position) {
long lockStamp = this.sl.tryOptimisticRead();
char result = (char) ((this.data[position] << 8) | (this.data[position + 1] & 0xff));
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
result = (char) ((this.data[position] << 8) | (this.data[position + 1] & 0xff));
} finally {
this.sl.unlockRead(lockStamp);
}
}
return result;
}
/**
* Gets the concept sequence.
*
* @return the concept sequence
*/
public int getConceptSequence() {
if (this.externalData) {
return this.identifierService.getConceptSequenceForUuids(new UUID(getLong(), getLong()));
}
return getInt();
}
/**
* Gets the data.
*
* @return the byte[] that backs this buffer.
*/
public byte[] getData() {
return this.data;
}
/**
* Gets the double.
*
* @return the double
*/
public double getDouble() {
return Double.longBitsToDouble(getLong());
}
/**
* Gets the double.
*
* @param position the position
* @return the double
*/
public double getDouble(int position) {
return Double.longBitsToDouble(getLong(position));
}
/**
* Checks if external data.
*
* @return true, if external data
*/
public boolean isExternalData() {
return this.externalData;
}
//~--- set methods ---------------------------------------------------------
/**
* Sets the external data.
*
* @param externalData the new external data
*/
public void setExternalData(boolean externalData) {
if (externalData) {
this.identifierService = Get.identifierService();
this.stampService = Get.stampService();
}
this.externalData = externalData;
}
//~--- get methods ---------------------------------------------------------
/**
* Gets the float.
*
* @return the float
*/
public float getFloat() {
return Float.intBitsToFloat(getInt());
}
/**
* Gets the float.
*
* @param position the position
* @return the float
*/
public float getFloat(int position) {
return Float.intBitsToFloat(getInt(position));
}
/**
* Gets the.
*
* @param src the src
* @param offset the offset
* @param length the length
*/
public void get(byte[] src, int offset, int length) {
get(this.position, src, offset, length);
this.position += length;
}
/**
* Gets the.
*
* @param position the position
* @param src the src
* @param offset the offset
* @param length the length
*/
public void get(int position, byte[] src, int offset, int length) {
long lockStamp = this.sl.tryOptimisticRead();
System.arraycopy(this.data, position, src, offset, length);
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
System.arraycopy(this.data, position, src, offset, length);
} finally {
this.sl.unlockRead(lockStamp);
}
}
}
/**
* Gets the int.
*
* @return the int
*/
public int getInt() {
final int result = getInt(this.position);
this.position += 4;
return result;
}
/**
* Gets the int.
*
* @param position the position
* @return the int
*/
public int getInt(int position) {
long lockStamp = this.sl.tryOptimisticRead();
int result = (((this.data[position]) << 24) | ((this.data[position + 1] & 0xff) << 16)
| ((this.data[position + 2] & 0xff) << 8) | ((this.data[position + 3] & 0xff)));
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
result = (((this.data[position]) << 24) | ((this.data[position + 1] & 0xff) << 16)
| ((this.data[position + 2] & 0xff) << 8) | ((this.data[position + 3] & 0xff)));
} finally {
this.sl.unlockRead(lockStamp);
}
}
return result;
}
/**
* Gets the int array.
*
* @return the int array
*/
public int[] getIntArray() {
final int[] array = new int[getInt()];
final int startingPosition = this.position;
long lockStamp = this.sl.tryOptimisticRead();
for (int i = 0; i < array.length; i++) {
array[i] = (((this.data[this.position]) << 24) | ((this.data[this.position + 1] & 255) << 16)
| ((this.data[this.position + 2] & 255) << 8) | ((this.data[this.position + 3] & 255)));
this.position += 4;
}
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
this.position = startingPosition;
try {
for (int i = 0; i < array.length; i++) {
array[i] = (((this.data[this.position]) << 24) | ((this.data[this.position + 1] & 255) << 16)
| ((this.data[this.position + 2] & 255) << 8) | ((this.data[this.position + 3] & 255)));
this.position += 4;
}
} finally {
this.sl.unlockRead(lockStamp);
}
}
return array;
}
/**
* The limit is the index of the first element that should not be read or written, relative to the position start.
* It represents the end of valid data, and is never negative and is never greater than its capacity.
* @return the position after the end of written data in the buffer, relative to the position start.
*/
public int getLimit() {
this.used = Math.max(this.used, this.position);
return this.used - this.positionStart;
}
/**
* Gets the long.
*
* @return the long
*/
public long getLong() {
final long result = getLong(this.position);
this.position += 8;
return result;
}
/**
* Gets the long.
*
* @param position the position
* @return the long
*/
public long getLong(int position) {
long lockStamp = this.sl.tryOptimisticRead();
long result = getLongResult(position);
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
result = getLongResult(position);
} finally {
this.sl.unlockRead(lockStamp);
}
}
return result;
}
/**
* Gets the long result.
*
* @param position the position
* @return the long result
*/
private long getLongResult(int position) {
long result;
result = ((((long) this.data[position]) << 56) | (((long) this.data[position + 1] & 0xff) << 48)
| (((long) this.data[position + 2] & 0xff) << 40) | (((long) this.data[position + 3] & 0xff) << 32)
| (((long) this.data[position + 4] & 0xff) << 24) | (((long) this.data[position + 5] & 0xff) << 16)
| (((long) this.data[position + 6] & 0xff) << 8) | (((long) this.data[position + 7] & 0xff)));
return result;
}
/**
* Gets the nid.
*
* @return the nid
*/
public int getNid() {
if (this.externalData) {
return this.identifierService.getNidForUuids(new UUID(getLong(), getLong()));
}
return getInt();
}
/**
* Gets the object data format version.
*
* @return the object data format version
*/
public byte getObjectDataFormatVersion() {
return this.objectDataFormatVersion;
}
//~--- set methods ---------------------------------------------------------
/**
* Sets the object data format version.
*
* @param objectDataFormatVersion the new object data format version
*/
public void setObjectDataFormatVersion(byte objectDataFormatVersion) {
this.objectDataFormatVersion = objectDataFormatVersion;
}
//~--- get methods ---------------------------------------------------------
/**
* The index of the next element to be read or written, relative to the position start.
* The position is never negative and is never greater than its limit.
* @return the index of the next element to be read or written.
*/
public int getPosition() {
return this.position - this.positionStart;
}
//~--- set methods ---------------------------------------------------------
/**
* Set the index of the next element to be read or written, relative to the position start.
* @param position the index of the next element to be read or written, relative to the position start.
*/
public void setPosition(int position) {
this.used = Math.max(this.used, this.position);
this.position = position + this.positionStart;
}
//~--- get methods ---------------------------------------------------------
/**
* The position start for this ByteArrayDataBuffer. Since many ByteArrayDataBuffers may
* use the same underlying data, the position start must be honored as the origin
* of data for this buffer, and a rewind or clear operation should only go back to position start.
* @return the position start for this ByteArrayDataBuffer.
*/
public int getPositionStart() {
return this.positionStart;
}
/**
* Gets the sememe sequence.
*
* @return the sememe sequence
*/
public int getSememeSequence() {
if (this.externalData) {
return this.identifierService.getSememeSequenceForUuids(new UUID(getLong(), getLong()));
}
return getInt();
}
/**
* Gets the short.
*
* @return the short
*/
public short getShort() {
final short result = getShort(this.position);
this.position += 2;
return result;
}
/**
* Gets the short.
*
* @param position the position
* @return the short
*/
public short getShort(int position) {
long lockStamp = this.sl.tryOptimisticRead();
short result = (short) (((this.data[position] & 0xff) << 8) | (this.data[position + 1] & 0xff));
if (!this.sl.validate(lockStamp)) {
lockStamp = this.sl.readLock();
try {
result = (short) (((this.data[position] & 0xff) << 8) | (this.data[position + 1] & 0xff));
} finally {
this.sl.unlockRead(lockStamp);
}
}
return result;
}
/**
* Gets the stamp sequence.
*
* @return the stamp sequence
*/
public int getStampSequence() {
if (this.externalData) {
return StampUniversal.get(this)
.getStampSequence();
}
return getInt();
}
/**
* Gets the uuid.
*
* @return the uuid
*/
public UUID getUuid() {
return new UUID(getLong(), getLong());
}
}