casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
ColumnDesc.h
Go to the documentation of this file.
00001 //# ColumnDesc.h: an envelope class for column descriptions in tables
00002 //# Copyright (C) 1994,1995,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 //# $Id: ColumnDesc.h 21130 2011-10-18 07:39:05Z gervandiepen $
00027 
00028 #ifndef TABLES_COLUMNDESC_H
00029 #define TABLES_COLUMNDESC_H
00030 
00031 
00032 //# Includes
00033 #include <casa/aips.h>
00034 #include <tables/Tables/BaseColDesc.h>
00035 #include <casa/Containers/SimOrdMap.h>
00036 #include <casa/BasicSL/String.h>
00037 #include <casa/Arrays/IPosition.h>
00038 #include <casa/OS/Mutex.h>
00039 
00040 namespace casa { //# NAMESPACE CASA - BEGIN
00041 
00042 // <summary>
00043 // Envelope class for the description of a table column
00044 // </summary>
00045 
00046 // <use visibility=export>
00047 
00048 // <reviewed reviewer="Paul Shannon" date="1994/08/11" tests="none">
00049 // </reviewed>
00050 
00051 // <prerequisite>
00052 //   <li> Tables module (see especially Tables.h, the module header file)
00053 //   <li> Envelope/Letter class design (see J. Coplien, Advanced C++)
00054 // </prerequisite>
00055 
00056 // <synopsis>
00057 // Class ColumnDesc is an envelope for the letter class BaseColDesc
00058 // and its derivations like
00059 // <linkto class="ScalarColumnDesc:description">ScalarColumnDesc</linkto>,
00060 // <linkto class="ScalarRecordColumnDesc:description">
00061 //  ScalarRecordColumnDesc</linkto>.
00062 // <linkto class="ArrayColumnDesc:description">ArrayColumnDesc</linkto>, and
00063 // <linkto class="SubTableDesc:description">SubTableDesc</linkto>.
00064 // ColumnDesc is meant to examine or slightly modify already existing
00065 // column descriptions.
00066 // It allows the retrieval of attributes like name, data type, etc..
00067 // For non-const ColumnDesc objects it is possible to modify the
00068 // attributes comment and keyword set.
00069 //
00070 // Since there are several types of columns, the class ColumnDesc
00071 // cannot handle all details of those column types. Therefore,
00072 // to create a column description, an instance of the specialized
00073 // classes ArrayColumnDesc<T>, etc. has to be constructed.
00074 // In there column type dependent things like array shape and
00075 // default value can be defined.
00076 //
00077 // This class also enumerates the possible options which can be used
00078 // when defining a column via classes like ScalarColumnDesc<T>.
00079 // These options are:
00080 // <dl>
00081 //  <dt> FixedShape
00082 //  <dd>
00083 //     This is only useful for columns containing arrays and tables.
00084 //     FixedShape means that the shape of the array or table must
00085 //     be the same in each cell of the column.
00086 //     If not given, the array or table shape may vary.
00087 //     Option Direct forces FixedShape.
00088 //  <dt> Direct
00089 //  <dd>
00090 //     This is only useful for columns containing arrays and tables.
00091 //     Direct means that the data is directly stored in the table.
00092 //     Direct forces option FixedShape.
00093 //     If not given, the array or table is indirect, which implies
00094 //     that the data will be stored in a separate file.
00095 //  <dt> Undefined
00096 //  <dd>
00097 //     Undefined is only useful for scalars. If not given, all possible
00098 //     values of the scalar have a meaning. If given, a value equal to
00099 //     the default value in the column description is an undefined value.
00100 //     The function TableColumn::isDefined will return False for such
00101 //     values.
00102 // </dl>
00103 // </synopsis>
00104 
00105 // <example>
00106 // <srcblock>
00107 //  TableDesc tableDesc("theTableDesc", TableDesc::New);
00108 //  // Add a float scalar column.
00109 //  tableDesc.addColumn (ScalarColumnDesc<float> ("NAME");
00110 //  // Get the description of a column and change the comments.
00111 //  // In order to change the comments, a reference must be used
00112 //  // (because the ColumnDesc copy constructor and assign have copy
00113 //  // semantics).
00114 //  ColumnDesc& myColDesc = tableDesc.columnDesc ("aName");
00115 //  myColDesc.comment() += "some more comments";
00116 // </srcblock>
00117 // </example>
00118 
00119 // <motivation>
00120 // When getting the description of an arbitrary column, a pointer to
00121 // that description is needed to allow proper execution of virtual
00122 // functions.
00123 // An envelope class is needed to hide this from the user.
00124 // </motivation>
00125 
00126 // <todo asof="$DATE:$">
00127 //# A List of bugs, limitations, extensions or planned refinements.
00128 // </todo>
00129 
00130 
00131 class ColumnDesc
00132 {
00133 friend class ColumnDescSet;
00134 friend class ColumnSet;
00135 friend class BaseColumn;
00136 
00137 public:
00138 
00139     // Enumerate the possible column options.
00140     // They can be combined by adding (logical or-ing) them.
00141     enum Option {
00142         // direct table or array
00143         Direct=1,
00144         // undefined values are possible
00145         Undefined=2,
00146         // fixed array/table shape
00147         FixedShape=4
00148     };
00149 
00150     // Construct from a column description.
00151     // This constructor is merely for the purpose of the automatic
00152     // conversion of an object like ScalarColumnDesc<T> to
00153     // ColumnDesc when adding a column to the table description
00154     // using the function TableDesc::addColumn.
00155     ColumnDesc (const BaseColumnDesc&);
00156 
00157     // Copy constructor (copy semantics).
00158     ColumnDesc (const ColumnDesc& that);
00159 
00160     // Default constructor (needed for ColumnDescSet).
00161     ColumnDesc()
00162       : colPtr_p(0),
00163         allocated_p (False)
00164     {}
00165 
00166     ~ColumnDesc();
00167 
00168     // Assignment (copy semantics).
00169     ColumnDesc& operator= (const ColumnDesc& that);
00170 
00171     // Comparison.
00172     // Two descriptions are equal when their data types, value types
00173     // (scalar, array or table) and possible dimensionalities are equal.
00174     // <group>
00175     Bool operator== (const ColumnDesc&) const;
00176     Bool operator!= (const ColumnDesc&) const;
00177     // </group>
00178 
00179     // Get access to the set of keywords.
00180     // <group>
00181     TableRecord& rwKeywordSet()
00182         { return colPtr_p->rwKeywordSet(); }
00183     const TableRecord& keywordSet() const
00184         { return colPtr_p->keywordSet(); }
00185     // </group>
00186 
00187     // Get the name of the column.
00188     //# Maybe it can be inlined.
00189     const String& name() const;
00190 
00191     // Get the data type of the column.
00192     // This always returns the type of a scalar, even when the column
00193     // contains arrays.
00194     DataType dataType() const
00195         { return colPtr_p->dataType(); }
00196 
00197     // Get the true data type of the column.
00198     // Unlike dataType, it returns an array data type (e.g. TpArrayInt)
00199     // when the column contains arrays.
00200     DataType trueDataType() const;
00201 
00202     // Get the type id for non-standard data types (i.e. for TpOther).
00203     // For standard data types the returned string is empty.
00204     const String& dataTypeId() const
00205         { return colPtr_p->dataTypeId(); }
00206 
00207     // Get the type name of the default data manager.
00208     const String& dataManagerType() const
00209         { return colPtr_p->dataManagerType(); }
00210 
00211     // Get the type name of the default data manager
00212     // (allowing it to be changed).
00213     String& dataManagerType()
00214         { return colPtr_p->dataManagerType(); }
00215 
00216     // Get the data manager group.
00217     const String& dataManagerGroup() const
00218         { return colPtr_p->dataManagerGroup(); }
00219 
00220     // Get the data manager group.
00221     // (allowing it to be changed).
00222     String& dataManagerGroup()
00223         { return colPtr_p->dataManagerGroup(); }
00224 
00225     // If <src>always==True</src> they are always set, otherwise only if empty.
00226     void setDefaultDataManager (Bool always=True)
00227         { colPtr_p->setDefaultDataManager (always); }
00228 
00229     // Get comment string.
00230     const String& comment() const
00231         { return colPtr_p->comment(); }
00232 
00233     // Get comment string (allowing it to be changed).
00234     String& comment()
00235         { return colPtr_p->comment(); }
00236 
00237     // Get the options. The possible options are defined by the enum Option.
00238     // E.g.
00239     // <srcblock>
00240     //    const ColumnDesc& coldesc = tableDesc.getColumn ("column_name");
00241     //    if (coldesc.option() & ColumnDesc::Direct  ==  ColumnDesc::Direct) {
00242     //            // the column has the Direct flag set
00243     //    }
00244     // </srcblock>
00245     int options() const
00246         { return colPtr_p->options(); }
00247 
00248     // Check if the column is defined with a fixed shape.
00249     // This is always true for scalars. For arrays it is true when
00250     // the FixedShape flag was set when the column was defined.
00251     Bool isFixedShape() const;
00252 
00253     // Test if column is a scalar.
00254     Bool isScalar() const
00255         { return colPtr_p->isScalar(); }
00256     // Test if column is an array.
00257     Bool isArray() const
00258         { return colPtr_p->isArray(); }
00259     // Test if column is a table.
00260     Bool isTable() const
00261         { return colPtr_p->isTable(); }
00262 
00263     // Get the number of dimensions.
00264     Int ndim() const
00265         { return colPtr_p->ndim(); }
00266 
00267     // Get the predefined shape.
00268     // If not defined, a zero shape will be returned.
00269     const IPosition& shape() const
00270         { return colPtr_p->shape(); }
00271 
00272     // Set the number of dimensions.
00273     // This is only allowed for arrays.
00274     // <src>ndim</src> can be zero to clear the number of dimensions
00275     // and the shape.
00276     // Otherwise it can only be used if the dimensionality has not been
00277     // defined yet.
00278     void setNdim (uInt ndim)
00279         { colPtr_p->setNdim (ndim); }
00280 
00281     // Set the predefined shape.
00282     // This is only allowed for arrays, for which the shape
00283     // has not been defined yet.
00284     // If the dimensionality has already been defined, it must match.
00285     // It will set the option <src>FixedShape</src> if not set yet.
00286     // <br> The first version leaves the <src>Direct</src> option as is.
00287     // The second version sets the <src>Direct</src> option as given.
00288     // <group>
00289     void setShape (const IPosition& shape)
00290         { colPtr_p->setShape (shape); }
00291     void setShape (const IPosition& shape, Bool directOption)
00292         { colPtr_p->setShape (shape, directOption); }
00293     // </group>
00294 
00295     // Set the options to the given value.
00296     // Option <src>ColumnDesc::Direct</src> forces <src>FixedShape</src>.
00297     // If <src>FixedShape</src> is not given (implicitly or explicitly),
00298     // the column can have no shape, so its shape is cleared.
00299     void setOptions (int options)
00300         { colPtr_p->setOptions (options); }
00301 
00302     // Get the maximum value length.
00303     uInt maxLength() const
00304         { return colPtr_p->maxLength(); }
00305 
00306     // Set the maximum value length.
00307     // So far, this is only possible for columns containing String values.
00308     // An exception is thrown if the column data type is not TpString.
00309     // Some storage managers support fixed length strings and can store
00310     // them more efficiently than variable length strings.
00311     void setMaxLength (uInt maxLength)
00312         { colPtr_p->setMaxLength (maxLength); }
00313 
00314     // Get table description (in case column contains subtables).
00315     // <group>
00316     const TableDesc* tableDesc() const
00317         { return colPtr_p->tableDesc(); }
00318     TableDesc* tableDesc()
00319         { return colPtr_p->tableDesc(); }
00320     // </group>
00321 
00322     // Show the column on cout.
00323     void show() const;
00324 
00325     // Show the column.
00326     void show (ostream& os) const;
00327 
00328     // Write into AipsIO.
00329     friend AipsIO& operator<< (AipsIO& ios, const ColumnDesc& cd);
00330 
00331     // Read from AipsIO.
00332     friend AipsIO& operator>> (AipsIO& ios, ColumnDesc& cd);
00333 
00334     // Show on ostream.
00335     friend ostream& operator<< (ostream& ios, const ColumnDesc& cd);
00336 
00337     // Set the name of the column.
00338     void setName (const String& name)
00339         { colPtr_p->setName(name); }
00340 
00341     // Create a RefColumn column object out of this column description.
00342     RefColumn* makeRefColumn (RefTable* rtp, BaseColumn* bcp) const
00343         { return colPtr_p->makeRefColumn (rtp, bcp); }
00344 
00345     // Create a ConcatColumn column object out of this column description.
00346     ConcatColumn* makeConcatColumn (ConcatTable* rtp) const
00347         { return colPtr_p->makeConcatColumn (rtp); }
00348 
00349 
00350     // Define the type of a XXColumnDesc construction function.
00351     typedef BaseColumnDesc* ColumnDescCtor (const String& className);
00352 
00353     // Get a construction function for a XXColumnDesc object (thread-safe).
00354     static ColumnDescCtor* getCtor (const String& name);
00355 
00356     // Register a "XXColumnDesc" constructor (thread-safe).
00357     static void registerCtor (const String& name, ColumnDescCtor*);
00358 
00359     // Register the main data managers (if not done yet).
00360     // It is fully thread-safe.
00361     static void registerMainCtor()
00362       { theirMutexedInit.exec(); }
00363 
00364 private:
00365     // Register a constructor without doing a mutex lock.
00366     static void unlockedRegisterCtor (const String& type, ColumnDescCtor* func)
00367       { theirRegisterMap.define (type, func); }
00368 
00369     // Define a map which maps the name of the various XXColumnDesc
00370     // classes to a static function constructing them.
00371     // This is used when reading a column description back; it in fact
00372     // determines the exact column type and is an easier thing to do
00373     // than an enormous switch statement.
00374     // The map is filled with the main XXColumnDesc construction functions
00375     // by the function registerColumnDesc upon the first call of
00376     // <src>ColumnDesc::getFile</src>.
00377     static MutexedInit theirMutexedInit;
00378     static SimpleOrderedMap<String, BaseColumnDesc* (*)(const String&)> theirRegisterMap;
00379 
00380     // Serve as default function for theirRegisterMap (see below),
00381     // which catches all unknown XXColumnDesc class names.
00382     // <thrown>
00383     //   <li> TableUnknownDesc
00384     // </thrown>
00385     static BaseColumnDesc* unknownColumnDesc (const String& name);
00386 
00387     // Do the actual (thread-safe) registration of the main data managers.
00388     static void doRegisterMainCtor (void*);
00389 
00390 private:
00391     // Construct from a pointer (for class BaseColumn).
00392     ColumnDesc (BaseColumnDesc*);
00393 
00394     // Check if a column can be handled by ColumnDescSet.
00395     // It is called before the column gets actually added, etc..
00396     // <group>
00397     // Check if the column can be added to the table description.
00398     // It is implemented for a virtual column to check if the columns
00399     // it uses really exist.
00400     void checkAdd (const ColumnDescSet& cds) const
00401         { colPtr_p->checkAdd (cds); }
00402     // Check when a column gets renamed in a table description.
00403     // It is not used.
00404     void checkRename (const ColumnDescSet& cds, const String& newName) const
00405         { colPtr_p->checkRename (cds, newName); }
00406     // </group>
00407 
00408     // Take action after a column has been handled by ColumnDescSet.
00409     // It is called after the column has been actually added, etc..
00410     // This gives, for instance, the virtual column class the opportunity
00411     // to update the virtual column list.
00412     // <group>
00413     void handleAdd (ColumnDescSet& cds)
00414         { colPtr_p->handleAdd (cds); }
00415     void handleRename (ColumnDescSet& cds, const String& oldName)
00416         { colPtr_p->handleRename (cds, oldName); }
00417     void handleRemove (ColumnDescSet& cds)
00418         { colPtr_p->handleRemove (cds); }
00419     // </group>
00420 
00421     // This function allows each column to act upon a rename of another column.
00422     // If the old name is used internally, the column can update itself.
00423     // It is called after handleRename has been called.
00424     void renameAction (const String& newName, const String& oldName)
00425         { colPtr_p->renameAction (newName, oldName); }
00426 
00427     // Create a PlainColumn column object out of this column description.
00428     PlainColumn* makeColumn (ColumnSet* csp) const
00429         { return colPtr_p->makeColumn (csp); }
00430 
00431     // Store the object in AipsIO.
00432     void putFile (AipsIO& ios, const TableAttr&) const;
00433 
00434     // Get the object from AipsIO.
00435     void getFile (AipsIO&, const TableAttr&);
00436 
00437 
00438 protected:
00439     BaseColumnDesc* colPtr_p;
00440     Bool            allocated_p;    //# False = not allocated -> do not delete
00441 };
00442 
00443 
00444 } //# NAMESPACE CASA - END
00445 
00446 #endif