if (parentRecords.contains(record)) {
throw new RecordException("A record may not be nested in itself: " + record.getId());
}
RecordType recordType;
QName recordRecordTypeName = record.getRecordTypeName();
if (recordRecordTypeName != null) {
if (valueTypeRecordTypeName != null) {
// Validate the same record type is being used
// 20130314: temporarily disabled this, see LILY-1279
// if (!valueTypeRecordTypeName.equals(recordRecordTypeName)) {
// throw new RecordException("The record's Record Type '" + recordRecordTypeName +
// "' does not match the record value type's record type '" + valueTypeRecordTypeName + "'");
// }
}
recordType = typeManager.getRecordTypeByName(recordRecordTypeName, null);
} else if (valueTypeRecordTypeName != null) {
recordType = typeManager.getRecordTypeByName(valueTypeRecordTypeName, null);
} else {
throw new RecordException("The record '" + record + "' should specify a record type");
}
// Get and sort the field type entries that should be in the record
List<FieldType> fieldTypes = getSortedFieldTypes(recordType);
Map<QName, Object> recordFields = record.getFields();
List<QName> expectedFields = new ArrayList<QName>();
// Write the record type information
// Encoding:
// - encoding version : byte (1)
// - nr of bytes in recordtype id : vInt
// - recordtype id : bytes
// - recordtype version : long
dataOutput.writeByte(ENCODING_VERSION);
byte[] recordIdBytes = recordType.getId().getBytes();
dataOutput.writeVInt(recordIdBytes.length);
dataOutput.writeBytes(recordIdBytes);
dataOutput.writeLong(recordType.getVersion());
// Write the content of the fields
// Encoding: for each field :
// - if not present in the record : undefined marker : byte (0)
// - if present in the record : defined marker : byte (1)
// - fieldValue : bytes
for (FieldType fieldType : fieldTypes) {
QName name = fieldType.getName();
expectedFields.add(name);
Object fieldValue = recordFields.get(name);
if (fieldValue == null) {
dataOutput.writeByte(UNDEFINED);
} else {
dataOutput.writeByte(DEFINED);
parentRecords.push(record);
fieldType.getValueType().write(fieldValue, dataOutput, parentRecords);
parentRecords.pop();
}
}
// Check if the record does contain fields that are not defined in the record type
if (!expectedFields.containsAll(recordFields.keySet())) {
throw new InvalidRecordException("Record contains fields not part of the record type '" +
recordType.getName() + "'", record.getId());
}
}