OERecord

An OERecord is a data container that holds a variety of strongly-typed, named values, plus associated metadata. It is used to pass data between cubes in Orion workfloes, and is the main mechanism by which data is communicated to and from Orion. OERecords also provide a general way to create and store structured data within the OpenEye ecosystem.

The most straightforward use of an OERecord is for storage and retrieval of simple values. The following example illustrates how to use a record to store and retrieve integer, string, and floating point values.

OERecord record;
auto intField = OEMakeField("My Integer Field", Types::Int);
auto stringField = OEMakeField("My String Field", Types::String);
auto floatField = OEMakeField("My Float Field", Types::Float);

record.SetValue(intField, 12345);
record.SetValue(stringField, "Hello World!");
record.SetValue(floatField, 67.89);

string value = record.GetValue(stringField);
cout << value << endl;  // "Hello World!"

cout << record.GetValue(intField) << endl;  // 12345
cout << record.GetValue(floatField) << endl;  // 67.89

OERecord has methods that allow you to interrogate the record for the presence of fields and values.

bool hasValue = record.HasValue(intField);  // true
bool hasField = record.HasField(intField);  // true

// Remove the value from a field
record.ClearValue(intField);

// The value is cleared, but the field still exists
cout << record.HasValue(intField) << endl;  // false
cout << record.HasField(intField) << endl;  // true
OELongLong intValue;
bool ok = record.GetValue(intValue, intField);  // false
cout << record.GetValue(intField) << endl;  // default constructed int: 0

// Remove the field
record.DeleteField(intField);
cout << record.HasField(intField) << endl;  // false
cout << record.GetValue(intField) << endl;  // default constructed int (0)

Other types of data can be stored on OERecords, including molecules and even other OERecords.

// We'll store a molecule on a new record
OERecord record2;
auto molField = OEMakeField("Molecule", Types::Chem::Mol);
OEMol mol;
OESmilesToMol(mol, "c1cc[nH]c1CC2COCNC2");
record2.SetValue(molField, mol);
cout << record2.GetValue(molField).NumAtoms() << endl;  // 12

// Now let's store another record on this one
auto recordField = OEMakeField("Check this out", Types::Record);
record2.SetValue(recordField, record);

OERecords can be written to files and read from files using the OEWriteRecord and OEReadRecord functions.

// Save our record to a file
oeofstream ofs("MyRecord.oedb");
OEWriteRecord(ofs, record2);
ofs.close();

oeifstream ifs("MyRecord.oedb");
OERecord newRecord;
OEReadRecord(newRecord, ifs);
OERecord childRecord = newRecord.GetValue(recordField);
cout << childRecord.HasField(floatField) << endl;  // true
cout << childRecord.GetValue(floatField) << endl;  // 67.89

Metadata on fields

In addition to holding various types of data, OERecord can also hold various pieces of metadata about its fields. The metadata is stored onto field objects using the OEFieldMeta class and constants from the OEMetadata class.

There are two types of metadata: options which are simple flags, and attributes which are key/value pairs with user-supplied values.

In the following example, two pieces of metadata, one option and one attribute, are put on a field to describe the contents of that field.

OERecord rec;

// Write a SMILES string onto a record, and provide a hint, using 
// metadata, that this string is in SMILES notation.
OEFieldMeta meta;
meta.SetOption(OEMetadata::Hints::Chem::SMILES);
meta.SetAttribute(OEMetadata::Display::Values::Priority, 1);
auto smilesField = OEMakeField("SMILES string", Types::String, meta);
rec.SetValue(smilesField, "c1ccccc1CCOC");

OEFieldMeta metaFromRecord = rec.GetFieldMeta("SMILES string");
cout << metaFromRecord.HasOption(OEMetadata::Hints::Chem::SMILES) << endl;  // true
cout << metaFromRecord.GetAttribute<int>(OEMetadata::Display::Values::Priority) << endl;  // 1

Metadata can also be used to designate relationships between fields on a record. The following example shows how to attach error values to a field using metadata.

auto valueField = OEMakeField("value", Types::Float);
OEFieldMeta errMeta;

// Add an "Errors For" relationship, referencing the valueField
errMeta.AddRelation(OEMetadata::Relations::ErrorsFor, valueField);
auto errField = OEMakeField("error", Types::Float, errMeta);
rec.SetValue(valueField, 46.5);
rec.SetValue(errField, 0.34);