TableRecord.h

Go to the documentation of this file.
00001 //# TableRecord.h: A hierarchical collection of named fields of various types
00002 //# Copyright (C) 1996,1997,1998,2000,2001,2002
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //#
00027 //# $Id$
00028 
00029 
00030 #ifndef TABLES_TABLERECORD_H
00031 #define TABLES_TABLERECORD_H
00032 
00033 //# Includes
00034 #include <casacore/casa/aips.h>
00035 #include <casacore/casa/Containers/RecordInterface.h>
00036 #include <casacore/tables/Tables/TableRecordRep.h>
00037 #include <casacore/casa/Containers/RecordDesc.h>
00038 #include <casacore/casa/Utilities/COWPtr.h>
00039 
00040 namespace casacore { //# NAMESPACE CASACORE - BEGIN
00041 
00042 //# Forward Declarations
00043 template<class T> class Array;
00044 class IPosition;
00045 class AipsIO;
00046 class TableLock;
00047 
00048 
00049 // <summary>
00050 // A hierarchical collection of named fields of various types
00051 // </summary>
00052 
00053 // <use visibility=export>
00054 // <reviewed reviewer="Mark Wieringa" date="1996/04/15" tests="tTableRecord">
00055 // </reviewed>
00056 
00057 // <prerequisite>
00058 //   <li> <linkto class="RecordDesc">RecordDesc</linkto>.
00059 //   <li> <linkto class="RecordFieldPtr">RecordFieldPtr</linkto>.
00060 // </prerequisite>
00061 //
00062 // <etymology>
00063 // TableRecord is a Record to be used in the Table system.
00064 // </etymology>
00065 //
00066 // <synopsis>
00067 // Class <linkto class=RecordInterface>RecordInterface</linkto> describes
00068 // the fundamental properties of records.
00069 // <br>
00070 // The TableRecord class is a particular type of a record class.
00071 // The fields in TableRecord may be of scalar type, array type, a Table
00072 // or a TableRecord.
00073 // The types are chosen to be compatible with the native
00074 // types of the Table system, viz: Bool, uChar, Short, Int, uInt, Float,
00075 // Double, Complex, DComplex, String.
00076 // Arrays of all these types are also available.
00077 // Note that a TableRecord is not a space-efficient way of storing
00078 // small objects.
00079 // <p>
00080 // The structure of a TableRecord is defined by the
00081 // <linkto class="RecordDesc">RecordDesc</linkto> class.
00082 // The structure of the TableRecord can be defined at
00083 // construction time. It can thereafter be restructured. This has the
00084 // effect, however, that any existing RecordFieldPtr objects become
00085 // invalid (using the <linkto file="Notice.h">Notice</linkto> classes).
00086 // <br>
00087 // It is possible to add or remove fields once a TableRecord is constructed.
00088 // However, this is not possible when the TableRecord is constructed with a
00089 // fixed structure (i.e. with the fixedStructure flag set).
00090 // <p>
00091 // A TableRecord is an hierarchical structure, because it can have fields
00092 // containing TableRecord's (as layed out in the RecordDesc). A subrecord
00093 // has a variable structure, when its RecordDesc is empty (i.e. contains
00094 // no fields). It is fixed when its RecordDesc contains fields.
00095 // <p>
00096 // A TableRecord may be assigned to another only if they conform; that is if
00097 // their fields have the identical type in the identical order.
00098 // The field names do not need to be identical however, only the types.
00099 // That is, the structure needs to be identical, but
00100 // not the labels. Note that field order is significant, 
00101 // <src>[ifield(type=Int),ffield(type=Float)]</src>
00102 // is not the same as <src>[ffield(type=Float),ifield(type=Int)]</src>
00103 // <br>
00104 // Conformance is checked recursively for fixed subrecords. That is, a
00105 // variable structured subrecord is not checked, because any record
00106 // can be assigned to it. A fixed structured subrecord has to
00107 // conform the corresponding subrecord in the source.
00108 // <br> A Table field is conforming when the name of the table
00109 // description of the source table matches the table description name
00110 // defined in the RecordDesc field. When that name is blank, every
00111 // table matches. In fact, defining a table description name is identical
00112 // to defining an array shape..
00113 // <p>
00114 // When a TableRecord is read back, possible Tables contained in fields
00115 // are only opended and read back when they are accessed for the first time.
00116 // In that way no needless table opens are done.
00117 // When a table has been opened, it is possible to close it. This
00118 // can be useful to save memory usage.
00119 // <p>
00120 // TableRecord uses copy-on-write semantics. This means that when a
00121 // TableRecord is copied, only the pointer to the underlying
00122 // TableRecordRep object is copied.
00123 // Only when the TableRecord gets changed (i.e. when a non-const
00124 // TableRecord member function is called), the TableRecordRep object is copied.
00125 // This results in a cheap copy behaviour.
00126 // </synopsis>
00127 //
00128 // <example>
00129 // <srcblock>
00130 //  {
00131 //    TableDesc td ("td", TableDesc::Scratch);
00132 //    td.addColumn (ScalarColumnDesc<Int> ("col1"));
00133 //    td.addColumn (ScalarColumnDesc<float> ("col2"));
00134 //    SetupNewTable newtab ("tTableRecord_tmp.tab1", td1, Table::New);
00135 //    Table tab (newtab, 10);
00136 //    RecordDesc rd;
00137 //    rd.addTable ("tab1", "td");            // with description name
00138 //    rd.addField ("tab2", TpTable);         // without description name
00139 //    TableRecord rec (rd, RecordInterface::Variable);
00140 //    // Both define's are possible.
00141 //    // The first one because the table description name matches.
00142 //    // The second one because that field has no table description name,
00143 //    // thus every table description matches.
00144 //    rec.defineTable (rec.fieldNumber("tab1"), tab1);
00145 //    rec.defineTable (rec.fieldNumber("tab2"), tab1);
00146 //    Table t1 = rec.asTable ("tab1");
00147 //    AlwaysAssertExit (t1.nrow() == 10  &&  t1.tableDesc().ncolumn() == 2);
00148 //    Table t2 = rec.asTable ("tab2");
00149 //    AlwaysAssertExit (t2.nrow() == 10  &&  t2.tableDesc().ncolumn() == 2);
00150 //    AipsIO aos ("file.name", ByteIO::New);
00151 //    aos << rec;
00152 //  }
00153 //    // Note that he above is put in a separate scope to be sure that
00154 //    // all objects are deleted and tables are written.
00155 //  {
00156 //    TableRecord rec;
00157 //    AipsIO aos ("file.name");
00158 //    aos >> rec;
00159 //    // At this point the record is read back, but the tables are not opened.
00160 //    // The next statement accesses the table resulting in its open.
00161 //    Table t1 = rec.asTable ("tab1");
00162 //    // The following statement closes it again.
00163 //    rec.closeTable ("tab1");
00164 // </srcblock>
00165 // </example>
00166 //
00167 // <motivation>
00168 // In principle the class Record could also support data type Table.
00169 // However, this would have had the big disadvantage that all the
00170 // Table code would have be linked in when only a simple Record is needed.
00171 // It was decided that for that reason it was better to support tables
00172 // in a separate class.
00173 // </motivation>
00174 //
00175 // <todo asof="1995/08/22">
00176 //   <li> A record reference class, which contains some fields from another
00177 //        record, would likely be useful. This would be analagous to a
00178 //        subarray sliced from an existing array.
00179 // </todo>
00180 
00181 
00182 class TableRecord : public RecordInterface
00183 {
00184 friend class TableRecordRep;
00185 
00186 public:
00187     // Create a record with no fields.
00188     // The record has a variable structure.
00189     TableRecord();
00190 
00191     // Create a record with no fields.
00192     // The type determines if the record has a fixed or variable structure.
00193     // The callback function is called when a field is added to the Record.
00194     // That function can check the name and of data type of the new field
00195     // (for instance, the Table system uses it to ensure that table columns
00196     // and keywords have different names).
00197     explicit TableRecord (RecordType type,
00198                           CheckFieldFunction* = 0,
00199                           const void* checkArgument = 0);
00200 
00201     // Create a record with the given description. If it is not possible to 
00202     // create all fields (for example, if a field with an unsupported data
00203     // type is requested), an exception is thrown.
00204     // The type determines if the record has a fixed or variable structure.
00205     // All fields are checked by the field checking function (if defined)
00206     // (for instance, the Table system uses it to ensure that table columns
00207     // and keywords have different names).
00208     explicit TableRecord (const RecordDesc& description,
00209                           RecordType type = Fixed,
00210                           CheckFieldFunction* = 0, 
00211                           const void* checkArgument = 0);
00212 
00213     // Create a copy of other using copy semantics.
00214     TableRecord (const TableRecord& other);
00215 
00216     // Create a TableRecord from another type of record.
00217     // It uses copy-on-write semantics if possible (i.e. if
00218     // <src>other</src> is a TableRecord), otherwise each field is copied.
00219     // Subrecords are also copied and converted to TableRecords if needed.
00220     TableRecord (const RecordInterface& other);
00221 
00222     // Copy the data in the other record to this record.
00223     // It can operate in 2 ways depending on the TableRecord structure flag.
00224     // <ul>
00225     // <li> For variable structured records the existing fields are
00226     //      thrown away and replaced by the new fields.
00227     //      This means that RecordFieldPtr's using this record get invalidated.
00228     //      Because copy-on-write semantics are used, this kind of
00229     //      assignment is a very efficient operation.
00230     // <li> For fixed structured records the existing values are replaced
00231     //      by the new values. This means that RecordFieldPtr's using this
00232     //      record remain valid.
00233     //      The structure of the other record has to conform this record
00234     //      or this record has to be empty, otherwise an exception is thrown.
00235     //      This assignment is less efficient, because it has to check the
00236     //      conformance and because each value has to be copied.
00237     // </ul>
00238     // <note role=warning>
00239     // Attributes like fixed structure flag and check function will not
00240     // be copied.
00241     // </note>
00242     TableRecord& operator= (const TableRecord& other);
00243     
00244     // Release resources associated with this object.
00245     ~TableRecord();
00246 
00247     // Make a copy of this object.
00248     virtual RecordInterface* clone() const;
00249 
00250     // Assign that RecordInterface object to this one.
00251     // If <src>that</src> is a TableRecord, copy-on-write is used.
00252     // Otherwise each individual field is copied.
00253     virtual void assign (const RecordInterface& that);
00254 
00255     // Convert the TableRecord to a Record (recursively).
00256     // A possible Table object is converted to a string containing
00257     // the table name preceeded by 'Table: ' (as used by TableProxy).
00258     Record toRecord() const;
00259 
00260     // Fill the TableRecord from the given Record.
00261     // The fields are appended to the TableRecord.
00262     // It is the opposite of toRecord, so a String containg 'Table: '
00263     // is handled as a Table (if it exists).
00264     void fromRecord (const Record& rec);
00265 
00266     // Get or define the value as a ValueHolder.
00267     // This is useful to pass around a value of any supported type.
00268     // <group>
00269     virtual ValueHolder asValueHolder (const RecordFieldId&) const;
00270     virtual void defineFromValueHolder (const RecordFieldId&,
00271                                         const ValueHolder&);
00272     // </group>
00273 
00274     // Get the comment for this field.
00275     virtual const String& comment (const RecordFieldId&) const;
00276 
00277     // Set the comment for this field.
00278     virtual void setComment (const RecordFieldId&, const String& comment);
00279 
00280     // Describes the current structure of this TableRecord.
00281     const RecordDesc& description() const;
00282 
00283     // Change the structure of this TableRecord to contain the fields in
00284     // newDescription. After calling restructure, <src>description() ==
00285     // newDescription</src>. Any existing RecordFieldPtr objects are
00286     // invalidated (their <src>isAttached()</src> members return False) after
00287     // this call.
00288     // <br>When the new description contains subrecords, those subrecords
00289     // will be restructured if <src>recursive=True</src> is given.
00290     // Otherwise the subrecord is a variable empty record.
00291     // Subrecords will be variable if their description is empty (i.e. does
00292     // not contain any field), otherwise they are fixed.
00293     // <br>Restructuring is not possible and an exception is thrown
00294     // if the Record has a fixed structure.
00295     virtual void restructure (const RecordDesc& newDescription,
00296                               Bool recursive=True);
00297 
00298     // Returns True if this and other have the same RecordDesc, other
00299     // than different names for the fields. That is, the number, type and the
00300     // order of the fields must be identical (recursively for fixed
00301     // structured sub-Records in this).
00302     // <note role=caution>
00303     // <src>thisRecord.conform(thatRecord) == True</src> does not imply
00304     // <br><src>thatRecord.conform(thisRecord) == True</src>, because
00305     // a variable record in one conforms a fixed record in that, but
00306     // not vice-versa.
00307     // </note>
00308     Bool conform (const TableRecord& other) const;
00309 
00310     // How many fields does this structure have? A convenient synonym for
00311     // <src>description().nfields()</src>.
00312     virtual uInt nfields() const;
00313 
00314     // Get the field number from the field name.
00315     // -1 is returned if the field name is unknown.
00316     virtual Int fieldNumber (const String& fieldName) const;
00317 
00318     // Get the data type of this field.
00319     virtual DataType type (Int whichField) const;
00320 
00321     // Remove a field from the record.
00322     // <note role=caution>
00323     // Removing a field means that the field number of the fields following
00324     // it will be decremented. Only the RecordFieldPtr's
00325     // pointing to the removed field will be invalidated.
00326     // </note>
00327     void removeField (const RecordFieldId&);
00328 
00329     // Rename the given field.
00330     void renameField (const String& newName, const RecordFieldId&);
00331 
00332     // Define a value for the given field.
00333     // When the field is unknown, it will be added to the record.
00334     // The second version is meant for any type of record (e.g. Record,
00335     // TableRecord, GlishRecord). It is converted to a TableRecord using the
00336     // TableRecord constructor taking a RecordInterface object.
00337     // <group>
00338     void defineRecord (const RecordFieldId&, const TableRecord& value,
00339                        RecordType type = Variable);
00340     virtual void defineRecord (const RecordFieldId&,
00341                                const RecordInterface& value,
00342                                RecordType = Variable);
00343     void defineTable  (const RecordFieldId&, const Table& value,
00344                        RecordType type = Variable);
00345     // </group>
00346 
00347     // Get the subrecord or table from the given field.
00348     // <note>
00349     // The non-const version has a different name to prevent that the
00350     // copy-on-write mechanism makes a copy when not necessary.
00351     // </note>
00352     // <group>
00353     const TableRecord& subRecord (const RecordFieldId&) const;
00354     TableRecord& rwSubRecord (const RecordFieldId&);
00355     virtual const RecordInterface& asRecord (const RecordFieldId&) const;
00356     virtual RecordInterface& asrwRecord (const RecordFieldId&);
00357     // </group>
00358 
00359     // Get the table from the given field.
00360     // By default the read/write option and lock options are inherited
00361     // from the parent table.
00362     // If openWritable=True, the table is still opened as readonly if the file
00363     // permissions do not permit write access.
00364     // <group>
00365     Table asTable (const RecordFieldId&) const;
00366     Table asTable (const RecordFieldId&, const TableLock& lockOptions) const;
00367     // </group>
00368 
00369     // Get the attributes of a table field.
00370     const TableAttr& tableAttributes (const RecordFieldId&) const;
00371 
00372     // Merge a field from another record into this record.
00373     // The DuplicatesFlag (as described in
00374     // <linkto class=RecordInterface>RecordInterface</linkto>) determines
00375     // what will be done in case the field name already exists.
00376     void mergeField (const TableRecord& other, const RecordFieldId&,
00377                      DuplicatesFlag = ThrowOnDuplicates);
00378 
00379     // Merge all fields from the other record into this record.
00380     // The DuplicatesFlag (as described in
00381     // <linkto class=RecordInterface>RecordInterface</linkto>) determines
00382     // what will be done in case a field name already exists.
00383     // An exception will be thrown if other is the same as this
00384     // (i.e. if merging the record itself).
00385     void merge (const TableRecord& other, DuplicatesFlag = ThrowOnDuplicates);
00386     
00387     // Close the table in the given field.
00388     // When accessed again, it will be opened automatically.
00389     // This can be useful to save memory usage.
00390     void closeTable (const RecordFieldId&) const;
00391 
00392     // Close all open tables.
00393     // When accessed again, it will be opened automatically.
00394     // This can be useful to save memory usage.
00395     void closeTables() const;
00396 
00397     // Flush all open subtables.
00398     void flushTables (Bool fsync=False) const;
00399 
00400     // Rename the subtables with a path containing the old parent table name.
00401     void renameTables (const String& newParentName,
00402                        const String& oldParentName);
00403 
00404     // Are subtables used in other processes.
00405     Bool areTablesMultiUsed() const;
00406 
00407     // Write the TableRecord to an output stream.
00408     friend AipsIO& operator<< (AipsIO& os, const TableRecord& rec);
00409 
00410     // Read the TableRecord from an input stream.
00411     friend AipsIO& operator>> (AipsIO& os, TableRecord& rec);
00412 
00413     // Put the data of a record.
00414     // This is used to write a subrecord, whose description has
00415     // not been written.
00416     void putRecord (AipsIO& os, const TableAttr&) const;
00417 
00418     // Read a record.
00419     // This is used to read a subrecord, whose description has
00420     // not been read.
00421     void getRecord (AipsIO& os, const TableAttr&);
00422 
00423     // Put the data of a record.
00424     // This is used to write a subrecord, whose description has
00425     // already been written.
00426     void putData (AipsIO& os, const TableAttr&) const;
00427 
00428     // Read the data of a record.
00429     // This is used to read a subrecord, whose description has
00430     // already been read.
00431     void getData (AipsIO& os, uInt version, const TableAttr&);
00432 
00433     // Print the contents of the record.
00434     // Only the first <src>maxNrValues</src> of an array will be printed.
00435     // A value < 0 means the entire array.
00436     virtual void print (std::ostream&,
00437                         Int maxNrValues = 25,
00438                         const String& indent="") const;
00439 
00440     // Reopen possible tables in keywords as read/write.
00441     // Tables are not reopened if they are not writable.
00442     void reopenRW();
00443 
00444     // Recursively set the attributes of subtables to the ones in the other
00445     // record for matching subtable field names. Otherwise set it to defaultAttr.
00446     // The name attribute is not changed.
00447     // It is primarily a helper function for PlainTable::syncTable
00448     // and ColumnSet::syncColumns.
00449     // <br>However, it can also be used to achieve that all subtables of a
00450     // read/write table are opened as readonly. E.g.:
00451     // <srcblock>
00452     //   TableAttr newAttr(String(), False, mainTable.lockOptions());
00453     //   mainTable.keywordSet().setTableAttr (TableRecord(), newAttr);
00454     // </srcblock>
00455     void setTableAttr (const TableRecord& other, const TableAttr& defaultAttr);
00456 
00457     // Make a unique record representation
00458     // (to do copy-on-write in RecordFieldPtr).
00459     virtual void makeUnique();
00460 
00461 
00462 protected:
00463     // Used by the RecordField classes to attach in a type-safe way to the
00464     // correct field.
00465     // <group>
00466     virtual void* get_pointer (Int whichField, DataType type) const;
00467     virtual void* get_pointer (Int whichField, DataType type,
00468                                const String& recordType) const;
00469     // </group>
00470 
00471     // Return a const reference to the underlying TableRecordRep.
00472     const TableRecordRep& ref() const;
00473 
00474     // Return a non-const reference to the underlying TableRecordRep.
00475     // When needed, the TableRecordRep will be copied and all RecordField
00476     // objects will be notified.
00477     TableRecordRep& rwRef();
00478 
00479     // Add a field to the record.
00480     virtual void addDataField (const String& name, DataType type,
00481                                const IPosition& shape, Bool fixedShape,
00482                                const void* value);
00483 
00484     // Define a value in the given field.
00485     virtual void defineDataField (Int whichField, DataType type,
00486                                   const void* value);
00487 
00488 private:
00489     // Get the description of this record.
00490     virtual RecordDesc getDescription() const;
00491 
00492     // Create TableRecord as a subrecord.
00493     // When the description is empty, the record has a variable structure.
00494     // Otherwise it is fixed.
00495     // <group>
00496     TableRecord (TableRecordRep* parent, const RecordDesc& description);
00497     TableRecord (TableRecordRep* parent, RecordType type);
00498     // </group>
00499 
00500     // Set the recordtype of this record and all its subrecords (recursively).
00501     void setRecordType (RecordType type);
00502 
00503     // The TableRecord representation.
00504     COWPtr<TableRecordRep> rep_p;
00505     // The parent TableRecord.
00506     TableRecordRep* parent_p;
00507 };
00508 
00509 
00510 
00511 inline const TableRecordRep& TableRecord::ref() const
00512 {
00513     return rep_p.ref();
00514 }
00515 inline const RecordDesc& TableRecord::description() const
00516 {
00517     return ref().description();
00518 }
00519 
00520 inline Bool TableRecord::conform (const TableRecord& other) const
00521 {
00522     return ref().conform (other.ref());
00523 }
00524 
00525 inline void TableRecord::putData (AipsIO& os,
00526                                   const TableAttr& parentAttr) const
00527 {
00528     ref().putData (os, parentAttr);
00529 }
00530 
00531 inline void TableRecord::getData (AipsIO& os, uInt version,
00532                                   const TableAttr& parentAttr)
00533 {
00534     rwRef().getData (os, version, parentAttr);
00535 }
00536 
00537 inline void TableRecord::reopenRW()
00538 {
00539     rwRef().reopenRW();
00540 }
00541 
00542 inline void TableRecord::closeTables() const
00543 {
00544     ref().closeTables();
00545 }
00546 
00547 inline void TableRecord::flushTables (Bool fsync) const
00548 {
00549     ref().flushTables (fsync);
00550 }
00551 
00552 inline void TableRecord::renameTables (const String& newParentName,
00553                                        const String& oldParentName)
00554 {
00555     rwRef().renameTables (newParentName, oldParentName);
00556 }
00557 
00558 inline Bool TableRecord::areTablesMultiUsed() const
00559 {
00560     return ref().areTablesMultiUsed();
00561 }
00562 
00563 
00564 
00565 } //# NAMESPACE CASACORE - END
00566 
00567 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1