/**
* Gets the requested version of the record (fields and recordTypes) from the Result object.
*/
public Record decodeRecord(RecordId recordId, Long requestedVersion, ReadContext readContext,
Result result, FieldTypes fieldTypes) throws InterruptedException, RepositoryException {
Record record = recordFactory.newRecord(recordId);
record.setVersion(requestedVersion);
// If the version is null, this means the record has no version an thus only contains non-versioned fields (if any)
// All non-versioned fields are stored at version 1, so we extract the fields at version 1
Long versionToRead = (requestedVersion == null) ? 1L : requestedVersion;
// Get a map of all fields with their values for each (cell-)version
NavigableMap<byte[], NavigableMap<Long, byte[]>> mapWithVersions = result.getMap().get(RecordCf.DATA.bytes);
if (mapWithVersions != null) {
// Iterate over all columns
for (Map.Entry<byte[], NavigableMap<Long, byte[]>> columnWithAllVersions : mapWithVersions.entrySet()) {
// Check if the retrieved column is from a data field, and not a system field
byte[] key = columnWithAllVersions.getKey();
if (key[0] == LilyHBaseSchema.RecordColumn.DATA_PREFIX) {
NavigableMap<Long, byte[]> allValueVersions = columnWithAllVersions.getValue();
// Get the entry for the version (can be a cell with a lower version number if the field was not changed)
Map.Entry<Long, byte[]> ceilingEntry = allValueVersions.ceilingEntry(versionToRead);
if (ceilingEntry != null) {
// Extract and decode the value of the field
ExtractedField field =
extractField(key, ceilingEntry.getValue(), readContext, fieldTypes);
if (field != null) {
record.setField(field.type.getName(), field.value);
if (field.metadata != null) {
record.setMetadata(field.type.getName(), field.metadata);
}
}
}
}
}
}
for (Scope scope : Scope.values()) {
Pair<SchemaId, Long> recordTypePair = requestedVersion == null ? extractLatestRecordType(scope, result) :
extractVersionRecordType(scope, result, requestedVersion);
if (recordTypePair != null) {
// We read the last version of the record type, though it might seem more logical to read
// the exact version stored in the record. However, this doesn't make any difference, since
// we just need the name of the record type, which is the same for all versions. The reason
// why reading the last version is preferred is because at the time of this writing, only
// the last version of record types is cached, and this makes an enormous difference in
// record read or scan speed.
QName recordTypeName =
typeManager.getRecordTypeById(recordTypePair.getV1(), null).getName();
record.setRecordType(scope, recordTypeName, recordTypePair.getV2());
if (readContext != null) {
readContext.setRecordTypeId(scope, recordTypePair.getV1());
}
}
}