RecordDesc.h

Go to the documentation of this file.
00001 //# RecordDesc.h: Description of the fields in a record object
00002 //# Copyright (C) 1995,1996,1998,2000,2001
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 CASA_RECORDDESC_H
00031 #define CASA_RECORDDESC_H
00032 
00033 
00034 //# Includes
00035 #include <casacore/casa/aips.h>
00036 #include <casacore/casa/Containers/RecordDescRep.h>
00037 #include <casacore/casa/Containers/RecordInterface.h>
00038 #include <casacore/casa/Utilities/COWPtr.h>
00039 #include <casacore/casa/iosfwd.h>
00040 
00041 namespace casacore { //# NAMESPACE CASACORE - BEGIN
00042 
00043 //# Forward Declarations
00044 class AipsIO;
00045 
00046 
00047 // <summary>
00048 // Description of the fields in a record object
00049 // </summary>
00050 
00051 // <use visibility=export>
00052 // <reviewed reviewer="Mark Wieringa" date="1996/04/15" tests="tRecordDesc">
00053 // </reviewed>
00054 
00055 // <prerequisite>
00056 //   <li> <linkto group="DataType.h#DataType">DataType</linkto>
00057 //   <li> <linkto class="Record">Record</linkto>
00058 // </prerequisite>
00059 //
00060 // <etymology>
00061 // RecordStructure would perhaps have been the clearest possible name. However
00062 // it was decided to name it ``RecordDesc'' to use a compatible naming
00063 // convention with other classes in the system, such as TableDesc. This class
00064 // <em>Desc</em>ribes the structure of a Record.
00065 // </etymology>
00066 //
00067 // <synopsis>
00068 // RecordDesc describes the structure of <linkto class="Record">Record</linkto>
00069 // objects. A Record consists of a number of fields. A RecordDesc describes 
00070 // those fields by assigning to each one:
00071 // <ul>
00072 //    <li> A name for the field.
00073 //    <li> A type from the <linkto group="DataType.h#DataType">DataType</linkto>
00074 //         enum.
00075 //    <li> A shape if the field is an array.
00076 //    <li> A RecordDesc if the field is itself a Record (the Record is an
00077 //         hierarchical structure).
00078 // </ul>
00079 // Only one field with a given name is allowed (although fields in subrecords
00080 // may have the same name as a field in a parent or child Record).
00081 //
00082 // Field indices are zero relative, i.e. they range from 0 to 
00083 // <src>nfields()-1</src>.
00084 // </synopsis>
00085 //
00086 // <example>
00087 // See the example in the description of the 
00088 // <linkto class="Record:example">Record</linkto> class.
00089 // </example>
00090 //
00091 // <motivation>
00092 // It is useful to be able to create many new objects with the same structure
00093 // as some other, without necessarily cloning it by copying all the values.
00094 // A ``Description'' type is necessary to do this (e.g., shape for an Array).
00095 // </motivation>
00096 //
00097 //
00098 // <todo asof="1995/06/01">
00099 //   <li> Should the strategy wrt. field names be changed (not used in
00100 //        field description equality, must be unique at a given level?).
00101 //   <li> Perhaps we should be able to more conveniently change the description
00102 //        of an existing field.
00103 // </todo>
00104 
00105 class RecordDesc
00106 {
00107 public:
00108     // Writes/reads the RecordDesc to/from an output stream.
00109     // <group name=io>
00110     friend ostream& operator<< (ostream& os, const RecordDesc& desc);
00111     friend AipsIO& operator<< (AipsIO& os, const RecordDesc& desc);
00112     friend AipsIO& operator>> (AipsIO& os, RecordDesc& desc);
00113     // </group>
00114 
00115     // Create a description with no fields.
00116     RecordDesc();
00117 
00118     // Create a description which is a copy of other.
00119     RecordDesc (const RecordDesc& other);
00120 
00121     // Replace this description with other.
00122     RecordDesc& operator= (const RecordDesc& other);
00123 
00124     ~RecordDesc();
00125 
00126     // Add scalar, array, sub-record, or table field.
00127     // If of array type, the shape is set to [-1], which indicates a
00128     // variable sized array.
00129     // If of sub-record type, the sub-record is free format.
00130     // Returns the number of fields in the description.
00131     uInt addField (const String& fieldName, DataType dataType);
00132 
00133     // Add an array field of the indicated type. The DataType is promoted
00134     // from a scalar type to an array type if necessary, e.g., 
00135     // <src>TpInt ->TpArrayInt</src>.  Returns the number of fields in
00136     // the description.
00137     // A shape of [-1] indicates a variable shape.
00138     uInt addField (const String& fieldName, DataType scalarOrArrayType,
00139                    const IPosition& shape);
00140 
00141     // Add a Record field to the description. This allows hierarchical
00142     // descriptions to be developed. Returns the number of fields in the
00143     // description.
00144     uInt addField (const String& fieldName, const RecordDesc& subDesc);
00145 
00146     // Add a Table field to the description. The Table description has the
00147     // given name. Returns the number of fields in the description.
00148     // <br>
00149     // When a table is put in a record field, it is checked if the name
00150     // of its description matches this name. If this name is empty, it
00151     // matches any table description.
00152     // <note role=warning>
00153     // Note that not all record types are able to instantiate a table field.
00154     // E.g. <linkto class=TableRecord>TableRecord</linkto> can instantiate
00155     // it, while <linkto class=Record>Record</linkto> cannot and throws an
00156     // exception when a record description containing a table field is used.
00157     // </note>
00158     uInt addTable (const String& fieldName, const String& tableDescName);
00159 
00160     // Get the comment for this field.
00161     const String& comment (Int whichField) const;
00162 
00163     // Set the comment for this field.
00164     void setComment (Int whichField, const String& comment);
00165 
00166     // Set the shape for this field.
00167     // An exception will be thrown if the field is no array.
00168     void setShape (Int whichField, const IPosition& shape);
00169 
00170     // Merge a single field from other.  If allowDuplicates is True, silently
00171     // throw away fields if one with the same name and type already exists,
00172     // otherwise an exception is thrown.  Conflicting types always cause an
00173     // exception. Returns the number of fields in the description.
00174     uInt mergeField (const RecordDesc& other, Int whichFieldFromOther,
00175                      RecordInterface::DuplicatesFlag DuplicateAction
00176                                        = RecordInterface::ThrowOnDuplicates);
00177 
00178     // Add all the fields from another RecordDesc to the current objects.
00179     // It returns the new number of fields.
00180     uInt merge (const RecordDesc& other, 
00181                 RecordInterface::DuplicatesFlag DuplicateAction
00182                                        = RecordInterface::ThrowOnDuplicates);
00183     
00184     // Remove the given field from the description.
00185     // It returns the new number of fields.
00186     uInt removeField (Int whichField);
00187 
00188     // Rename the given field.
00189     void renameField (const String& newName, Int whichField);
00190 
00191     // Returns the index of the field named fieldName. Returns -1 if fieldName
00192     // does not exist.
00193     Int fieldNumber (const String& fieldName) const;
00194 
00195     // Number of fields in the description.
00196     uInt nfields() const;
00197 
00198     // What is the type of the given field. Returns TpRecord if the field is
00199     // a sub-Record.
00200     DataType type (Int whichField) const;
00201 
00202     // What is the name of the given field.
00203     const String& name (Int whichField) const;
00204 
00205     // Create a name for a field defined by index as *i (similar to glish).
00206     // It takes care that the resulting name is unique by adding a suffix _j
00207     // when needed.
00208     String makeName (Int whichField) const;
00209 
00210     // Make the given name unique by adding a suffix _j when needed.
00211     // j is the minimal number needed to make it unique.
00212     String uniqueName (const String& name) const;
00213 
00214     // Returns True if whichField is an array.
00215     Bool isArray (Int whichField) const;
00216 
00217     // Returns True if whichField is a scalar.
00218     Bool isScalar (Int whichField) const;
00219 
00220     // Returns True if whichField is a sub-record.
00221     Bool isSubRecord (Int whichField) const;
00222 
00223     // Returns True if whichField is a table.
00224     Bool isTable (Int whichField) const;
00225 
00226     // What is the shape of the given field. Returns [1] if the field is a
00227     // scalar, table or, sub-record, [-1] if it is a variable length array,
00228     // and the actual shape for a fixed length array.
00229     const IPosition& shape (Int whichField) const;
00230 
00231     // What is the name of the table description.
00232     // Returns an empty string when the field is no table.
00233     const String& tableDescName (Int whichField) const;
00234 
00235     // If whichField is a sub-record return its description.
00236     // Otherwise an exception is thrown.
00237     // The non-const version is named differently to prevent accidental
00238     // use of the non-const version.
00239     // <group>
00240     const RecordDesc& subRecord (Int whichField) const;
00241     RecordDesc& rwSubRecord (Int whichField);
00242     // </group>
00243 
00244     // This and other compare equal if the field types and shapes are identical
00245     // (recursively if there are described sub-records).
00246     // The field names are not used.
00247     // <br>Use function isEqual if names are important, but order is not.
00248     // <group>
00249     Bool operator== (const RecordDesc& other) const;
00250     Bool operator!= (const RecordDesc& other) const;
00251     // </group>
00252 
00253     // Test if this description conforms the other.
00254     // It is NOT doing it recursively, thus is does not check if
00255     // sub-records are conforming.
00256     // <br>This is used by Record, to see if another record can be assigned
00257     // to this record.
00258     Bool conform (const RecordDesc& other) const;
00259 
00260     // Test if this description equals another one.
00261     // It is equal if the number of fields is equal and all field names in
00262     // this description occur in the other too. The order of the fields
00263     // is not important.
00264     // <br>The flag equalDataTypes is set to True if the data types
00265     // of all fields match.
00266     // <br>Use function operator== if order and types are important,
00267     // but names are not.
00268     Bool isEqual (const RecordDesc& other, Bool& equalDataTypes) const;
00269 
00270     // Test if this description is a subset of another one.
00271     // It is similar to isEqual above.
00272     Bool isSubset (const RecordDesc& other, Bool& equalDataTypes) const;
00273 
00274     // Test if this description is a strict subset of another one, thus
00275     // if it is a subset and not equal.
00276     Bool isStrictSubset (const RecordDesc& other, Bool& equalDataTypes) const;
00277 
00278     // Test if this description is a superset of another one.
00279     Bool isSuperset (const RecordDesc& other, Bool& equalDataTypes) const;
00280 
00281     // Test if this description is a strict superset of another one, thus
00282     // if it is a superset and not equal.
00283     Bool isStrictSuperset (const RecordDesc& other,
00284                            Bool& equalDataTypes) const;
00285 
00286     // Test if the set of field names in this and other record description
00287     // is disjoint (i.e. if they do not share names).
00288     Bool isDisjoint (const RecordDesc& other) const;
00289 
00290 
00291 private:
00292     // Writes/reads the RecordDesc to/from an output stream.
00293     // <group>
00294     ostream& put (ostream& os) const;
00295     AipsIO& put (AipsIO& os) const;
00296     AipsIO& get (AipsIO& os);
00297     // </group>
00298 
00299     // Use a copy-on-write pointer to the RecordDescRep.
00300     COWPtr<RecordDescRep> desc_p;
00301 };
00302 
00303 
00304 
00305 inline RecordDesc::RecordDesc()
00306 : desc_p (new RecordDescRep)
00307 {}
00308 
00309 inline RecordDesc::RecordDesc (const RecordDesc& other)
00310 : desc_p (other.desc_p)
00311 {}
00312 
00313 inline RecordDesc& RecordDesc::operator= (const RecordDesc& other)
00314 {
00315     if (this != &other) {
00316         desc_p = other.desc_p;
00317     }
00318     return *this;
00319 }
00320 
00321 inline RecordDesc::~RecordDesc()
00322 {}
00323 
00324 inline uInt RecordDesc::addField (const String& fieldName, DataType dataType)
00325 {
00326     return desc_p.rwRef().addField (fieldName, dataType);
00327 }
00328 
00329 inline uInt RecordDesc::addField (const String& fieldName,
00330                                   DataType scalarOrArrayType,
00331                                   const IPosition& shape)
00332 {
00333     return desc_p.rwRef().addArray (fieldName, scalarOrArrayType, shape);
00334 }
00335 
00336 inline uInt RecordDesc::addField (const String& fieldName,
00337                                   const RecordDesc& subDesc)
00338 {
00339     return desc_p.rwRef().addRecord (fieldName, subDesc);
00340 }
00341 
00342 inline uInt RecordDesc::addTable (const String& fieldName,
00343                                   const String& tableDescName)
00344 {
00345     return desc_p.rwRef().addTable (fieldName, tableDescName);
00346 }
00347 
00348 inline const String& RecordDesc::comment (Int whichField) const
00349 {
00350     return desc_p.ref().comment (whichField);
00351 }
00352 
00353 inline void RecordDesc::setComment (Int whichField, const String& comment)
00354 {
00355     desc_p.rwRef().setComment (whichField, comment);
00356 }
00357 
00358 inline void RecordDesc::setShape (Int whichField, const IPosition& shape)
00359 {
00360     desc_p.rwRef().setShape (whichField, shape);
00361 }
00362 
00363 inline uInt RecordDesc::mergeField (const RecordDesc& other,
00364                                Int whichFieldFromOther,
00365                                RecordInterface::DuplicatesFlag duplicateAction)
00366 {
00367     return desc_p.rwRef().mergeField (other.desc_p.ref(), whichFieldFromOther,
00368                                       duplicateAction);
00369 }
00370 
00371 inline uInt RecordDesc::merge (const RecordDesc& other,
00372                                RecordInterface::DuplicatesFlag duplicateAction)
00373 {
00374     return desc_p.rwRef().merge (other.desc_p.ref(), duplicateAction);
00375 }
00376     
00377 inline uInt RecordDesc::removeField (Int whichField)
00378 {
00379     return desc_p.rwRef().removeField (whichField);
00380 }
00381 
00382 inline void RecordDesc::renameField (const String& newName, Int whichField)
00383 {
00384     desc_p.rwRef().renameField (newName, whichField);
00385 }
00386  
00387 inline Int RecordDesc::fieldNumber (const String& fieldName) const
00388 {
00389     return desc_p.ref().fieldNumber (fieldName);
00390 }
00391 
00392 inline uInt RecordDesc::nfields() const
00393 {
00394     return desc_p.ref().nfields();
00395 }
00396 
00397 inline DataType RecordDesc::type (Int whichField) const
00398 {
00399     return desc_p.ref().type (whichField);
00400 }
00401 
00402 inline String RecordDesc::uniqueName (const String& name) const
00403 {
00404     return desc_p.ref().uniqueName (name);
00405 }
00406 
00407 inline String RecordDesc::makeName (Int whichField) const
00408 {
00409     return desc_p.ref().makeName (whichField);
00410 }
00411 
00412 inline const String& RecordDesc::name (Int whichField) const
00413 {
00414     return desc_p.ref().name (whichField);
00415 }
00416 
00417 inline Bool RecordDesc::isArray (Int whichField) const
00418 {
00419     return desc_p.ref().isArray (whichField);
00420 }
00421 
00422 inline Bool RecordDesc::isScalar (Int whichField) const
00423 {
00424     return desc_p.ref().isScalar (whichField);
00425 }
00426 
00427 inline Bool RecordDesc::isSubRecord (Int whichField) const
00428 {
00429     return desc_p.ref().isSubRecord (whichField);
00430 }
00431 
00432 inline Bool RecordDesc::isTable (Int whichField) const
00433 {
00434     return desc_p.ref().isTable (whichField);
00435 }
00436 
00437 inline const IPosition& RecordDesc::shape (Int whichField) const
00438 {
00439     return desc_p.ref().shape (whichField);
00440 }
00441 
00442 inline const String& RecordDesc::tableDescName (Int whichField) const
00443 {
00444     return desc_p.ref().tableDescName (whichField);
00445 }
00446 
00447 inline const RecordDesc& RecordDesc::subRecord (Int whichField) const
00448 {
00449     return desc_p.ref().subRecord (whichField);
00450 }
00451 
00452 inline RecordDesc& RecordDesc::rwSubRecord (Int whichField)
00453 {
00454     return desc_p.rwRef().subRecord (whichField);
00455 }
00456 
00457 inline Bool RecordDesc::operator== (const RecordDesc& other) const
00458 {
00459     return desc_p.ref() == other.desc_p.ref();
00460 }
00461 
00462 inline Bool RecordDesc::operator!= (const RecordDesc& other) const
00463 {
00464     return desc_p.ref() != other.desc_p.ref();
00465 }
00466 inline Bool RecordDesc::conform (const RecordDesc& other) const
00467 {
00468     return desc_p.ref().conform (other.desc_p.ref());
00469 }
00470 
00471 inline Bool RecordDesc::isEqual (const RecordDesc& other,
00472                                  Bool& equalDataTypes) const
00473 {
00474     return desc_p.ref().isEqual (other.desc_p.ref(), equalDataTypes);
00475 }
00476 inline Bool RecordDesc::isSubset (const RecordDesc& other,
00477                                   Bool& equalDataTypes) const
00478 {
00479     return desc_p.ref().isSubset (other.desc_p.ref(), equalDataTypes);
00480 }
00481 inline Bool RecordDesc::isStrictSubset (const RecordDesc& other,
00482                                         Bool& equalDataTypes) const
00483 {
00484     return desc_p.ref().isStrictSubset (other.desc_p.ref(), equalDataTypes);
00485 }
00486 inline Bool RecordDesc::isSuperset (const RecordDesc& other,
00487                                     Bool& equalDataTypes) const
00488 {
00489     return other.desc_p.ref().isSubset (desc_p.ref(), equalDataTypes);
00490 }
00491 inline Bool RecordDesc::isStrictSuperset (const RecordDesc& other,
00492                                           Bool& equalDataTypes) const
00493 {
00494     return other.desc_p.ref().isStrictSubset (desc_p.ref(), equalDataTypes);
00495 }
00496 inline Bool RecordDesc::isDisjoint (const RecordDesc& other) const
00497 {
00498     return desc_p.ref().isDisjoint (other.desc_p.ref());
00499 }
00500 
00501 
00502 inline ostream& operator<< (ostream& os, const RecordDesc& desc)
00503 {
00504     return desc.put (os);
00505 }
00506 inline AipsIO& operator<< (AipsIO& os, const RecordDesc& desc)
00507 {
00508     return desc.put (os);
00509 }
00510 inline AipsIO& operator>> (AipsIO& os, RecordDesc& desc)
00511 {
00512     return desc.get (os);
00513 }
00514 
00515 
00516 
00517 
00518 
00519 } //# NAMESPACE CASACORE - END
00520 
00521 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1