casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
RecordDescRep.h
Go to the documentation of this file.
00001 //# RecordDescRep.h: Representation of a RecordDesc
00002 //# Copyright (C) 1996,1997,1998,1999,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: RecordDescRep.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $
00028 
00029 
00030 #ifndef CASA_RECORDDESCREP_H
00031 #define CASA_RECORDDESCREP_H
00032 
00033 //# Includes
00034 #include <casa/aips.h>
00035 #include <casa/Utilities/DataType.h>
00036 #include <casa/Containers/Block.h>
00037 #include <casa/Containers/SimOrdMap.h>
00038 #include <casa/Arrays/IPosition.h>
00039 #include <casa/iosfwd.h>
00040 
00041 namespace casa { //# NAMESPACE CASA - BEGIN
00042 
00043 //# Forward Declarations
00044 class RecordDesc;
00045 class AipsIO;
00046 
00047 
00048 // <summary>
00049 // Representation of a RecordDesc
00050 // </summary>
00051 
00052 // <use visibility=local>
00053 // <reviewed reviewer="Mark Wieringa" date="1996/04/15" tests="tRecordDesc">
00054 // </reviewed>
00055 
00056 // <prerequisite>
00057 //   <li> <linkto group="DataType.h#DataType">DataType</linkto>
00058 //   <li> <linkto class="RecordDesc">RecordDesc</linkto>
00059 // </prerequisite>
00060 
00061 // <etymology>
00062 // Rep is an often used abbreviation for representation.
00063 // Thus RecordDescRep is the representation of a RecordDesc.
00064 // </etymology>
00065 
00066 // <synopsis>
00067 // RecordDescRep is used by RecordDesc
00068 // to implement its copy-on-write semantics. RecordDesc is the interface
00069 // to the user, while RecordDescRep contains the actual implementation.
00070 // See <linkto class=RecordDesc>RecordDesc</linkto> for a more detailed
00071 // description of a record description.
00072 // </synopsis>
00073 
00074 // <example>
00075 // See the example in the description of the 
00076 // <linkto class="Record:example">Record</linkto> class.
00077 // </example>
00078 
00079 // <motivation>
00080 // RecordDescRep is needed to make copy-on-write semantics possible in
00081 // class RecordDesc.
00082 // </motivation>
00083 
00084 // <todo asof="1995/06/01">
00085 //   <li> Should the strategy wrt. field names be changed (not used in
00086 //        field description equality, must be unique at a given level?).
00087 //   <li> Perhaps we should be able to more conveniently change the description
00088 //        of an existing field.
00089 // </todo>
00090 
00091 class RecordDescRep
00092 {
00093 public:
00094     // Create a description with no fields.
00095     RecordDescRep();
00096 
00097     // Create a description which is a copy of other.
00098     RecordDescRep (const RecordDescRep& other);
00099 
00100     // Replace this description with other.
00101     RecordDescRep& operator= (const RecordDescRep& other);
00102 
00103     virtual ~RecordDescRep();
00104 
00105     // Add scalar or array field. If of array type, the shape is set to [-1],
00106     // which indicates a variable sized array. Returns the number of fields in
00107     // the description.
00108     uInt addField (const String& fieldName, DataType scalarOrArrayType);
00109 
00110     // Add an array field of the indicated type. The DataType is promoted
00111     // from a scalar type to an array type if necessary, e.g., 
00112     // <src>TpInt ->TpArrayInt</src>.  Returns the number of fields in
00113     // the description.
00114     uInt addArray (const String& fieldName, DataType scalarOrArrayType,
00115                    const IPosition& shape);
00116 
00117     // Add a Record field to the description. This allows hierarchical
00118     // descriptions to be developed. Returns the number of fields in the
00119     // description.
00120     uInt addRecord (const String& fieldName, const RecordDesc& subDesc);
00121 
00122     // Add a Table field to the description. The Table description has the
00123     // given name. Returns the number of fields in the description.
00124     uInt addTable (const String& fieldName, const String& tableDescName);
00125 
00126     // Get the comment for this field.
00127     const String& comment (Int whichField) const;
00128 
00129     // Set the comment for this field.
00130     void setComment (Int whichField, const String& comment);
00131 
00132     // Set the shape for this field.
00133     // An exception will be thrown if the field is no array.
00134     void setShape (Int whichField, const IPosition& shape);
00135 
00136     // Merge a single field from other.  If allowDuplicates is True, silently
00137     // throw away fields if one with the same name and type already exists,
00138     // otherwise an exception is thrown.  Conflicting types always cause an
00139     // exception. Returns the number of fields in the description.
00140     uInt mergeField (const RecordDescRep& other, Int whichFieldFromOther,
00141                      int duplicateAction);
00142 
00143     // Add all the fields from another RecordDescRep to the current objects.
00144     uInt merge (const RecordDescRep& other, int duplicateAction);
00145     
00146     // Remove the given field from the description.
00147     virtual uInt removeField (Int whichField);
00148 
00149     // Rename the given field.
00150     virtual void renameField (const String& newName, Int whichField);
00151 
00152     // Returns the index of the field named fieldName. Returns -1 if fieldName
00153     // does not exist.
00154     Int fieldNumber (const String& fieldName) const;
00155 
00156     // Number of fields in the description.
00157     uInt nfields() const;
00158 
00159     // What is the type of the given field. Returns TpRecord if the field is
00160     // a sub-Record.
00161     DataType type (Int whichField) const;
00162 
00163     // What is the name of the given field.
00164     const String& name (Int whichField) const;
00165 
00166     // Create a name for a field defined by index as *i (similar to glish).
00167     // It takes care that the resulting name is unique by adding a suffix _j
00168     // when needed.
00169     String makeName (Int whichField) const;
00170 
00171     // Make the given name unique by adding a suffix _j when needed.
00172     // j is the minimal number needed to make it unique.
00173     String uniqueName (const String& name) const;
00174 
00175     // Returns True if whichField is an array.
00176     Bool isArray (Int whichField) const;
00177 
00178     // Returns True if whichField is a scalar.
00179     Bool isScalar (Int whichField) const;
00180 
00181     // Returns True if whichField is a sub-record.
00182     Bool isSubRecord (Int whichField) const;
00183 
00184     // Returns True if whichField is a table.
00185     Bool isTable (Int whichField) const;
00186 
00187     // What is the shape of the given field. Returns [1] if the field is a
00188     // scalar, table or, sub-record, [-1] if it is a variable length array,
00189     // and the actual shape for a fixed length array.
00190     const IPosition& shape (Int whichField) const;
00191 
00192     // What is the name of the table description associated with a table.
00193     const String& tableDescName (Int whichField) const;
00194 
00195     // If whichField is a sub-record with a description,
00196     // return its description. Otherwise an exception is thrown.
00197     // <group>
00198     const RecordDesc& subRecord (Int whichField) const;
00199     RecordDesc& subRecord (Int whichField);
00200     // </group>
00201 
00202     // <group>
00203     // This and other compare equal if the field types and shapes are identical
00204     // (recursively if there are described sub-records or tables).
00205     // The field names are not used.
00206     Bool operator== (const RecordDescRep& other) const;
00207     Bool operator!= (const RecordDescRep& other) const;
00208     // </group>
00209 
00210     // Test if this description conforms the other.
00211     // It is similar to operator==. However, a subrecord in that description
00212     // always conforms an arbitrary (i.e. empty) subrecord in this
00213     // description.
00214     // <br>This is used by Record, to see if another record can be assigned
00215     // to this record.
00216     Bool conform (const RecordDescRep& other) const;
00217 
00218     // Test if this description equals another one.
00219     // It is equal if the number of fields is equal and all field names in
00220     // this description occur in the other too. The order of the fields
00221     // is not important.
00222     // <br>The flag equalDataTypes is set to True if the data types
00223     // of all fields match.
00224     // <br>Use function operator== if order and types are important,
00225     // but names are not.
00226     Bool isEqual (const RecordDescRep& other, Bool& equalDataTypes) const;
00227 
00228     // Test if this description is a subset of another one.
00229     // It is similar to isEqual above.
00230     Bool isSubset (const RecordDescRep& other, Bool& equalDataTypes) const;
00231 
00232     // Test if this description is a strict subset of another one, thus
00233     // if it is a subset and not equal.
00234     Bool isStrictSubset (const RecordDescRep& other,
00235                          Bool& equalDataTypes) const;
00236 
00237     // Test if the set of field names in this and other record description
00238     // is disjoint (i.e. if they do not share names).
00239     Bool isDisjoint (const RecordDescRep& other) const;
00240 
00241 protected:
00242     // Add a field name and its type.
00243     // It checks if the name is unique and it extends the various blocks
00244     // using increment_length.
00245     void addFieldName (const String& fieldName, DataType type);
00246 
00247     // Add a field from another Record description.
00248     // This is used by the merge functions.
00249     virtual void addRepField (const RecordDescRep& other,
00250                               const String& newName, Int whichField);
00251 
00252     // Add the field info. These are helper functions for the add functions
00253     // and can be used in derived classes too.
00254     // <group>
00255     void addFieldAny (DataType scalarOrArrayType);
00256     void addFieldArray (DataType scalarOrArrayType, const IPosition& shape);
00257     // </group>
00258 
00259     // Set the shape (for a derived class).
00260     void setShape (const IPosition& shape, Int whichField);
00261 
00262     // Helper functions
00263     // <group>
00264     virtual void increment_length();
00265     void copy_other (const RecordDescRep& other);
00266     // </group>
00267 
00268 private:
00269     // Test if all fields are part of the other description.
00270     // The flag equalDataTypes is set to True if the data types of the
00271     // fields in both descriptions are the same.
00272     Bool allExist (const RecordDescRep&, Bool& equalDataTypes) const;
00273 
00274     // Number of fields in the description.
00275     uInt n_p;
00276     // The DataType of each field.
00277     Block<Int> types_p;
00278     // The name of each field.
00279     Block<String> names_p;
00280     // The description of the subrecords. Null if the field is not a subrecord.
00281     // This isn't the most efficient representation. If this is ever an issue
00282     // we could calculate these, or store them in one Block, or implement
00283     // copy-on-write semantics.
00284     PtrBlock<RecordDesc*> sub_records_p;
00285     // The shape of the field [1] for scalars and sub-records.
00286     Block<IPosition> shapes_p;
00287     // True if the corresponding field is an array.
00288     Block<Bool> is_array_p;
00289     // Table description name for table fields.
00290     Block<String> tableDescNames_p;
00291     // Comments for each field.
00292     Block<String> comments_p;
00293     // Mapping of field name to field number.
00294     SimpleOrderedMap<String,Int> name_map_p;
00295 };
00296 
00297 inline uInt RecordDescRep::nfields() const
00298 {
00299     return n_p;
00300 }
00301 
00302 inline DataType RecordDescRep::type (Int whichField) const
00303 {
00304     return DataType(types_p[whichField]);
00305 }
00306 
00307 inline const String& RecordDescRep::name (Int whichField) const
00308 {
00309     return names_p[whichField];
00310 }
00311 
00312 inline const IPosition& RecordDescRep::shape (Int whichField) const
00313 {
00314     return shapes_p[whichField];
00315 }
00316 
00317 inline Bool RecordDescRep::isArray (Int whichField) const
00318 {
00319     return is_array_p[whichField];
00320 }
00321 
00322 inline Bool RecordDescRep::isScalar (Int whichField) const
00323 {
00324     return isScalarFun (DataType(types_p[whichField]));
00325 }
00326 
00327 inline Bool RecordDescRep::isSubRecord (Int whichField) const
00328 {
00329     return  (types_p[whichField] == TpRecord);
00330 }
00331 
00332 inline Bool RecordDescRep::isTable (Int whichField) const
00333 {
00334     return  (types_p[whichField] == TpTable);
00335 }
00336 
00337 inline const RecordDesc& RecordDescRep::subRecord (Int whichField) const
00338 {
00339     //# The cast to non-const is completely safe.
00340     return ((RecordDescRep*)this)->subRecord (whichField);
00341 }
00342 
00343 inline const String& RecordDescRep::tableDescName (Int whichField) const
00344 {
00345     return tableDescNames_p[whichField];
00346 }
00347 
00348 
00349 
00350 } //# NAMESPACE CASA - END
00351 
00352 #endif