RecordInterface.h

Classes

RecordInterface -- Abstract base class for Record classes (full description)
RecordNotice -- Helper class to notify class Record about changes (full description)

class RecordInterface : public NoticeSource

Types

enum RecordType

Fixed
Record has a fixed structure; that is, no fields can be added or removed once the Record is created.
Variable
Record has a variable structure; after Record creation fields can be added or removed at will.

enum DuplicatesFlag

RenameDuplicates
Rename a name from the other set to name_n, where n is the first positive number making the name unique.
SkipDuplicates
Skip duplicate names from the other set.
OverwriteDuplicates
Overwrite the value of a duplicate keyword This will also happen when their types differ.
ThrowOnDuplicates
Throw an exception.

Interface

Public Members
typedef Bool CheckFieldFunction (const String& fieldName, DataType dataType, const void* extraArgument, String& message)
RecordInterface()
RecordInterface (RecordType type, CheckFieldFunction* funcPtr, const void* checkArgument)
RecordInterface (const RecordInterface& other)
RecordInterface& operator= (const RecordInterface& other)
~RecordInterface()
virtual RecordInterface* clone() const = 0
virtual void assign (const RecordInterface& that) = 0
Bool isFixed() const
virtual uInt nfields() const = 0
virtual Int fieldNumber (const String& fieldName) const = 0
Int idToNumber (const RecordFieldId&) const
Bool isDefined (const String& fieldName) const
virtual DataType type (Int whichField) const = 0
DataType dataType (const RecordFieldId&) const
String name (const RecordFieldId&) const
virtual const String& comment (const RecordFieldId&) const = 0
virtual void setComment (const RecordFieldId&, const String& comment) = 0
IPosition shape (const RecordFieldId&) const
RecordDesc description() const
virtual void restructure (const RecordDesc& newDescription, Bool recursive=True) = 0
virtual void removeField (const RecordFieldId&) = 0
void define (const RecordFieldId&, Bool value)
void define (const RecordFieldId&, uChar value)
void define (const RecordFieldId&, Short value)
void define (const RecordFieldId&, Int value)
void define (const RecordFieldId&, uInt value)
void define (const RecordFieldId&, Float value)
void define (const RecordFieldId&, Double value)
void define (const RecordFieldId&, const Complex& value)
void define (const RecordFieldId&, const DComplex& value)
void define (const RecordFieldId&, const Char* value)
void define (const RecordFieldId&, const String& value)
void define (const RecordFieldId&, const Array<Bool>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<uChar>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<Short>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<Int>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<uInt>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<Float>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<Double>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<Complex>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<DComplex>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<String>& value, Bool FixedShape = False)
virtual void defineRecord (const RecordFieldId&, const RecordInterface& value, RecordType = Variable) = 0
void get (const RecordFieldId&, Bool& value) const
void get (const RecordFieldId&, uChar& value) const
void get (const RecordFieldId&, Short& value) const
void get (const RecordFieldId&, Int& value) const
void get (const RecordFieldId&, uInt& value) const
void get (const RecordFieldId&, Float& value) const
void get (const RecordFieldId&, Double& value) const
void get (const RecordFieldId&, Complex& value) const
void get (const RecordFieldId&, DComplex& value) const
void get (const RecordFieldId&, String& value) const
void get (const RecordFieldId&, Array<Bool>& value) const
void get (const RecordFieldId&, Array<uChar>& value) const
void get (const RecordFieldId&, Array<Short>& value) const
void get (const RecordFieldId&, Array<Int>& value) const
void get (const RecordFieldId&, Array<uInt>& value) const
void get (const RecordFieldId&, Array<Float>& value) const
void get (const RecordFieldId&, Array<Double>& value) const
void get (const RecordFieldId&, Array<Complex>& value) const
void get (const RecordFieldId&, Array<DComplex>& value) const
void get (const RecordFieldId&, Array<String>& value) const
Bool asBool (const RecordFieldId&) const
uChar asuChar (const RecordFieldId&) const
Short asShort (const RecordFieldId&) const
Int asInt (const RecordFieldId&) const
uInt asuInt (const RecordFieldId&) const
Float asFloat (const RecordFieldId&) const
Double asDouble (const RecordFieldId&) const
Complex asComplex (const RecordFieldId&) const
DComplex asDComplex(const RecordFieldId&) const
const String& asString (const RecordFieldId&) const
const Array<Bool>& asArrayBool (const RecordFieldId&) const
const Array<uChar>& asArrayuChar (const RecordFieldId&) const
const Array<Short>& asArrayShort (const RecordFieldId&) const
const Array<Int>& asArrayInt (const RecordFieldId&) const
const Array<uInt>& asArrayuInt (const RecordFieldId&) const
const Array<Float>& asArrayFloat (const RecordFieldId&) const
const Array<Double>& asArrayDouble (const RecordFieldId&) const
const Array<Complex>& asArrayComplex (const RecordFieldId&) const
const Array<DComplex>& asArrayDComplex(const RecordFieldId&) const
const Array<String>& asArrayString (const RecordFieldId&) const
virtual const RecordInterface& asRecord (const RecordFieldId&) const = 0
virtual RecordInterface& asrwRecord (const RecordFieldId&) = 0
Array<Bool> toArrayBool (const RecordFieldId&) const
Array<uChar> toArrayuChar (const RecordFieldId&) const
Array<Short> toArrayShort (const RecordFieldId&) const
Array<Int> toArrayInt (const RecordFieldId&) const
Array<uInt> toArrayuInt (const RecordFieldId&) const
Array<Float> toArrayFloat (const RecordFieldId&) const
Array<Double> toArrayDouble (const RecordFieldId&) const
Array<Complex> toArrayComplex (const RecordFieldId&) const
Array<DComplex> toArrayDComplex(const RecordFieldId&) const
Array<String> toArrayString (const RecordFieldId&) const
Float asfloat (const RecordFieldId&) const
Double asdouble (const RecordFieldId&) const
const Array<Float>& asArrayfloat (const RecordFieldId&) const
const Array<Double>& asArraydouble (const RecordFieldId&) const
virtual void makeUnique() = 0
virtual void defineDataField (Int whichField, DataType type, const void* value) = 0
virtual void* get_pointer (Int whichField, DataType type) const = 0
virtual void* get_pointer (Int whichField, DataType type, const String& recordType) const = 0
Protected Members
virtual void addDataField (const String& name, DataType type, const IPosition& shape, Bool fixedShape, const void* value) = 0
void throwIfFixed() const
void checkName (const String& fieldName, DataType type) const
RecordType& recordType()
RecordType recordType() const
Int newIdToNumber (const RecordFieldId&) const
void defineField (const RecordFieldId&, DataType type, const void* value)
void defineField (const RecordFieldId&, DataType type, const IPosition& shape, Bool fixedShape, const void* value)
Private Members
virtual RecordDesc getDescription() const = 0

Description

Review Status

Reviewed By:
Mark Wieringa
Date Reviewed:
1996/04/15
Programs:
Tests:

Etymology

``Record'' is a widely used term in both programming languages and data structures to denote an imhogeneous set of fields. An alternative would have been to name it structure, which would have perhaps been a clearer name for C++ programmers.
RecordInterface denotes that this class defines the common interface to possible Record classes.

Synopsis

A Record is an inhomogeneous, hierarchical, collection of named fields. The fields may be of scalar type, array type, a Table or a Record. This latter feature is what makes the Record a (potentially) hierarchical type.

RecordInterface is the abstract base class for various Record classes. At the moment three Record classes exist:

Presently, the scalar types are chosen to be compatible with the native types of the Table system, viz: Bool, uChar, Short, Int, uInt, Float, Double, Complex, DComplex, String. Arrays of all these types are also available. It is fairly straightforward to extend this set if necessary, although it will result in more template instantiations with the current implementation.

Each field has an integral index, which ranges between 0 and nfields() - 1. The values of a field can be manipulated in two ways:

  1. Through the get and put functions in this class. They are easy to use and support type promotion. However, they are a bit less efficient than the second way.
  2. Through the class RecordFieldPtr. This is a bit less convenient. However, it is more efficient when the same field is accessed multiple times.
The structure of a record can be fixed or variable. When fixed, it is not possible to change the structure once the record has been instantiated. When variable, the record can be restructured or fields can be added/removed.
When a field gets added, it is possible to check if its name and type are valid by means of the CheckFunction callback. This is for instance used by the table system to assure that keywords and columns in a table do not have the same name.

Arrays in a record description can be fixed or variable shaped. When fixed shaped, only arrays with that shape can be stored in that field in the record. When variable shaped, any array can be stored.
However, note there is a difference between assign and define. Assign invokes the array assignment operator which checks for conformance. Thus even for variable shaped arrays, the new array must conform the exisitng one when using assign. Define simply replaces the array, thus for variable shaped arrays ay array shape will do.

RecordFieldPtr objects attached to a Record have to be notified when the Record is deleted or changed. The RecordInterface class provides the hooks for this via the Notice system. It is derived from NoticeSource. The class RecordNotice is for the messages.

Motivation

This common base class provides a common interface to the various Record classes. Furthermore it is needed for the class RecordFieldPtr. Finally it provides the hooks for the notification in case the record structure changes.

To Do

Member Description

enum RecordType

Define the flag telling if a Record has a fixed or variable structure.

enum DuplicatesFlag

Define the Duplicates flag for the function merge in the various record classes. This function merges the fields from that record (description) into this one. DuplicatesFlag determines what to do when a field already exists.

typedef Bool CheckFieldFunction (const String& fieldName, DataType dataType, const void* extraArgument, String& message)

Define the signature of the add callback function. This function is called when a field is added to the record (thus also when a Record is constructed from a RecordDesc). The function can check if the name and/or data type are valid. The extra argument is the argument given to the Record constructor which can be used to pass non-Record information. The function should return False when name or data type is invalid. In that case it can fill the message string, which will be added to the message in the thrown exception.

RecordInterface()

The default constructor creates an empty record with a variable structure.

RecordInterface (RecordType type, CheckFieldFunction* funcPtr, const void* checkArgument)

Create a record with no fields. The callback function is called when a field is added to the Record. That function can check the name and of data type of the new field (for instance, the Table system uses it to ensure that table columns and keywords have different names).

RecordInterface (const RecordInterface& other)

Copy constructor (copy semantics).

RecordInterface& operator= (const RecordInterface& other)

Assignment (copy semantics). This only assigns the RecordInterface object itself, thus not the data in a derived class. To do that the function assign below can be used.

~RecordInterface()

Destruct the record. All attached RecordFieldPtr objects are notified to detach themselves.

virtual RecordInterface* clone() const = 0

Make a copy of this object.

virtual void assign (const RecordInterface& that) = 0

Assign that RecordInterface object to this one. Unlike operator= it copies all data in the derived class.

Bool isFixed() const

Is the Record structure fixed (i.e. impossible to restructure or to add or remove fields)?

virtual uInt nfields() const = 0

How many fields does this structure have?

virtual Int fieldNumber (const String& fieldName) const = 0

Get the field number from the field name. -1 is returned if the field name is unknown.

Int idToNumber (const RecordFieldId&) const

Get the field number for the given field id. It throws an exception when an unknown name was given.

Bool isDefined (const String& fieldName) const

Test if a field name exists.

virtual DataType type (Int whichField) const = 0
DataType dataType (const RecordFieldId&) const

Get the data type of this field (as defined in DataType.h).

String name (const RecordFieldId&) const

Get the name of this field.

virtual const String& comment (const RecordFieldId&) const = 0

Get the comment for this field.

virtual void setComment (const RecordFieldId&, const String& comment) = 0

Set the comment for this field.

IPosition shape (const RecordFieldId&) const

Get the actual shape of this field. It returns [1] for non-array fields.

RecordDesc description() const

Get the description of this record.

virtual void restructure (const RecordDesc& newDescription, Bool recursive=True) = 0

Change the structure of this Record to contain the fields in newDescription. After calling restructure, description() == newDescription. Any existing RecordFieldPtr objects are invalidated (their isAttached() members return False) after this call.
When the new description contains subrecords, those subrecords will be restructured if recursive=True is given. Otherwise the subrecord is a variable empty record. Subrecords will be variable if their description is empty (i.e. does not contain any field), otherwise they are fixed.
Restructuring is not possible and an exception is thrown if the Record has a fixed structure.

virtual void removeField (const RecordFieldId&) = 0

Remove a field from the record.

Caution Removing a field means that the field number of the fields following it will be decremented. It will invalidate RecordFieldPtr's pointing to the removed field, but no other RecordFieldPtr's.

void define (const RecordFieldId&, Bool value)
void define (const RecordFieldId&, uChar value)
void define (const RecordFieldId&, Short value)
void define (const RecordFieldId&, Int value)
void define (const RecordFieldId&, uInt value)
void define (const RecordFieldId&, Float value)
void define (const RecordFieldId&, Double value)
void define (const RecordFieldId&, const Complex& value)
void define (const RecordFieldId&, const DComplex& value)
void define (const RecordFieldId&, const Char* value)
void define (const RecordFieldId&, const String& value)
void define (const RecordFieldId&, const Array<Bool>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<uChar>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<Short>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<Int>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<uInt>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<Float>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<Double>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<Complex>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<DComplex>& value, Bool FixedShape = False)
void define (const RecordFieldId&, const Array<String>& value, Bool FixedShape = False)
virtual void defineRecord (const RecordFieldId&, const RecordInterface& value, RecordType = Variable) = 0

Define a value for the given field. Array conformance rules will not be applied for variable shaped arrays. When the field and value data type mismatch, type promotion of scalars will be done if possible. If not possible, an exception is thrown.
When the field does not exist, it will be added to the record. This results in an exception for fixed structured records. The field is checked by a possible field checking function before it gets added.

void get (const RecordFieldId&, Bool& value) const
void get (const RecordFieldId&, uChar& value) const
void get (const RecordFieldId&, Short& value) const
void get (const RecordFieldId&, Int& value) const
void get (const RecordFieldId&, uInt& value) const
void get (const RecordFieldId&, Float& value) const
void get (const RecordFieldId&, Double& value) const
void get (const RecordFieldId&, Complex& value) const
void get (const RecordFieldId&, DComplex& value) const
void get (const RecordFieldId&, String& value) const
void get (const RecordFieldId&, Array<Bool>& value) const
void get (const RecordFieldId&, Array<uChar>& value) const
void get (const RecordFieldId&, Array<Short>& value) const
void get (const RecordFieldId&, Array<Int>& value) const
void get (const RecordFieldId&, Array<uInt>& value) const
void get (const RecordFieldId&, Array<Float>& value) const
void get (const RecordFieldId&, Array<Double>& value) const
void get (const RecordFieldId&, Array<Complex>& value) const
void get (const RecordFieldId&, Array<DComplex>& value) const
void get (const RecordFieldId&, Array<String>& value) const

Get the value of the given field. When the field and value data type mismatch, type promotion of scalars will be done if possible. If not possible, an exception is thrown. When the value argument is an array, it will be reshaped if needed.

Bool asBool (const RecordFieldId&) const
uChar asuChar (const RecordFieldId&) const
Short asShort (const RecordFieldId&) const
Int asInt (const RecordFieldId&) const
uInt asuInt (const RecordFieldId&) const
Float asFloat (const RecordFieldId&) const
Double asDouble (const RecordFieldId&) const
Complex asComplex (const RecordFieldId&) const
DComplex asDComplex(const RecordFieldId&) const
const String& asString (const RecordFieldId&) const
const Array<Bool>& asArrayBool (const RecordFieldId&) const
const Array<uChar>& asArrayuChar (const RecordFieldId&) const
const Array<Short>& asArrayShort (const RecordFieldId&) const
const Array<Int>& asArrayInt (const RecordFieldId&) const
const Array<uInt>& asArrayuInt (const RecordFieldId&) const
const Array<Float>& asArrayFloat (const RecordFieldId&) const
const Array<Double>& asArrayDouble (const RecordFieldId&) const
const Array<Complex>& asArrayComplex (const RecordFieldId&) const
const Array<DComplex>& asArrayDComplex(const RecordFieldId&) const
const Array<String>& asArrayString (const RecordFieldId&) const
virtual const RecordInterface& asRecord (const RecordFieldId&) const = 0
virtual RecordInterface& asrwRecord (const RecordFieldId&) = 0

The following functions get the value based on field name or number. The scalar functions promote the data type if needed. The array functions throw an exception if the data type mismatches. The get function or toArrayX function can be used for type promotion.

Array<Bool> toArrayBool (const RecordFieldId&) const
Array<uChar> toArrayuChar (const RecordFieldId&) const
Array<Short> toArrayShort (const RecordFieldId&) const
Array<Int> toArrayInt (const RecordFieldId&) const
Array<uInt> toArrayuInt (const RecordFieldId&) const
Array<Float> toArrayFloat (const RecordFieldId&) const
Array<Double> toArrayDouble (const RecordFieldId&) const
Array<Complex> toArrayComplex (const RecordFieldId&) const
Array<DComplex> toArrayDComplex(const RecordFieldId&) const
Array<String> toArrayString (const RecordFieldId&) const

Get an array while promoting the data as needed. A scalar value is also converted to an array. These functions are slower than asX, but more general.

Float asfloat (const RecordFieldId&) const
Double asdouble (const RecordFieldId&) const
const Array<Float>& asArrayfloat (const RecordFieldId&) const
const Array<Double>& asArraydouble (const RecordFieldId&) const

Get value based on field name or number. They are here for backward compatibility with the old KeywordSet classes and will be removed in the future.

virtual void makeUnique() = 0

Make a unique record representation (for copy-on-write in RecordFieldPtr).

virtual void defineDataField (Int whichField, DataType type, const void* value) = 0

Define a data field (for RecordFieldPtr).

virtual void* get_pointer (Int whichField, DataType type) const = 0
virtual void* get_pointer (Int whichField, DataType type, const String& recordType) const = 0

Used by the RecordFieldPtr classes to attach to the correct field. The latter function is used to attach to a Record-type field checking if the correct Record type is used.

virtual void addDataField (const String& name, DataType type, const IPosition& shape, Bool fixedShape, const void* value) = 0

Let the derived class add an array field with the given type, shape, and value.

void throwIfFixed() const

Check if the Record has a non-fixed structure. If it is fixed, it throws an exception. This can be used by other functions (like define).

void checkName (const String& fieldName, DataType type) const

Check if the new field name is correct. This is done by calling the checkFunction (if defined). If incorrect, an exception is thrown.

RecordType& recordType()
RecordType recordType() const

Give access to the RecordType flag (write-access is needed when a record is read back).

Int newIdToNumber (const RecordFieldId&) const

Get the field number for the given field id. It returns -1 when an unknown name was given.

void defineField (const RecordFieldId&, DataType type, const void* value)

Add a scalar field with the given type and value. An exception is thrown if the record structure is fixed or if the name is invalid.

void defineField (const RecordFieldId&, DataType type, const IPosition& shape, Bool fixedShape, const void* value)

Add an array field with the given type, shape and value. An exception is thrown if the record structure is fixed or if the name is invalid.

virtual RecordDesc getDescription() const = 0

Get the description of this record.

class RecordNotice : public Notice

Types

enum NoticeType

DETACH
Record has been deleted; detach all RecordFieldPtr's.
ACQUIRE
RecordRep has been copied; re-acquire the pointers in all RecordFieldPtr's.
REMOVE
A field has been removed; detach that RecordFieldPtr and decrement field numbers in RecordFieldPtr's following it.

Interface

Public Members
RecordNotice (NoticeType changeType, uInt fieldNumber)
virtual uInt type() const
virtual int operator== (const Notice& that) const
NoticeType changeType() const
Int fieldNumber() const

Description

Review Status

Reviewed By:
Mark Wieringa
Date Reviewed:
1996/04/15
Programs:
Tests:
  • tRecord

Prerequisite

Synopsis

This class is of essentially no interest. The Notification system which is used to invalidate RecordFieldPtr's to a destructed or changed record requires that a class derived from Notice be available to carry messages. There are 3 messages which are described below.

Member Description

enum NoticeType

Define the possible change types.

RecordNotice (NoticeType changeType, uInt fieldNumber)

Construct a notice for the given type and field number. The field number is only used for type REMOVE.

virtual uInt type() const

Returns the change type.

virtual int operator== (const Notice& that) const

Always returns False.

NoticeType changeType() const

Return the change type.

Int fieldNumber() const

Return the field number.