casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
MeasureHolder.h
Go to the documentation of this file.
00001 //# MeasureHolder.h: A holder for Measures to enable record conversions
00002 //# Copyright (C) 1998,1999,2000,2003
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: MeasureHolder.h 21024 2011-03-01 11:46:18Z gervandiepen $
00027 
00028 #ifndef MEASURES_MEASUREHOLDER_H
00029 #define MEASURES_MEASUREHOLDER_H
00030 
00031 //# Includes
00032 #include <casa/aips.h>
00033 #include <casa/Utilities/PtrHolder.h>
00034 #include <casa/Utilities/RecordTransformable.h>
00035 #include <casa/Containers/Block.h>
00036 
00037 namespace casa { //# NAMESPACE CASA - BEGIN
00038 
00039 //# Forward Declarations
00040 class Measure;
00041 class MDirection;
00042 class MDoppler;
00043 class MEpoch;
00044 class MFrequency;
00045 class MPosition;
00046 class MRadialVelocity;
00047 class Muvw;
00048 class MBaseline;
00049 class MEarthMagnetic;
00050 class MeasValue;
00051 
00052 // <summary> A holder for Measures to enable record conversions </summary>
00053 
00054 // <use visibility=export>
00055 
00056 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tMeasureHolder" demos="">
00057 // </reviewed>
00058 
00059 // <prerequisite>
00060 //   <li> <linkto class=RecordInterface>RecordInterface</linkto> class
00061 //   <li> <linkto class=Measure>Measure</linkto> class
00062 // </prerequisite>
00063 //
00064 // <etymology>
00065 // A Holder of general Measures
00066 // </etymology>
00067 //
00068 // <synopsis>
00069 // This class can be used to handle heterogeneous collections of Measures, e.g.
00070 // as a <src>Vector<MeasureHolder></src>. With the aid of the
00071 // toRecord() and fromRecord() functions it can be used
00072 // to convert a Measure object into or from a record.
00073 // A MeasureHolder is created from a Measure, or can be empty.
00074 //
00075 // Checks on the contents can be made with functions like
00076 // <src>isMDirection</src> and the contents can be obtained with
00077 // functions like <src>asMDirection</src>. It is an error to try and
00078 // retrieve a measure of the wrong type and doing so will generate an
00079 // exception (AipsError).
00080 //
00081 // The MeasureHolder can, in addition to the Measure it is holding, also hold
00082 // a block of MeasValues. This is especially useful for intertask
00083 // communication (e.g. with Glish), for reasons of speed. In general the
00084 // additional values will be created when the record used to create
00085 // a Holder contains a <src>Quantity<Vector></src> rather than a quantity in
00086 // the m0, m1 and/or m2 fields. The <src>getMV()</src> method can be used to
00087 // access the <src>nelements()</src> additional information. They can be
00088 // (re-)set with the <src>setMV()</src> method (after a possible creation
00089 // of the extra block if not already there, or of the wrong length, 
00090 // with <src>makeMV()</src>. If any value is set they will be used in
00091 // creating records, with the first value always overwriting the actual
00092 // Measure value.
00093 //
00094 // </synopsis>
00095 //
00096 // <example>
00097 // <srcblock>
00098 //      TableRecord rec;
00099 //      MDirection dir(MVDirection(Quantity(12.5, 'deg'), Quantity(-2, 'deg')),
00100 //                     MDirection::J2000);
00101 //      String error;           // error message
00102 //      if (!MeasureHolder(dir).toRecord(error, rec)) {
00103 //              cout << error << endl;
00104 //      }
00105 //      Record grec;            // a Record
00106 //      if (!MeasureHolder(dir).toRecord(error, grec)) {  // make record
00107 //              cout << error << endl;
00108 //      }
00109 // // Note that for GlishRecords use can be made of the
00110 // // GlishRecord::to/fromrecord() methods.
00111 // </srcblock>
00112 // </example>
00113 //
00114 // <motivation>
00115 // To make general conversions between Measures and records, without knowing
00116 // the actual Measure being converted.
00117 // </motivation>
00118 
00119 class MeasureHolder : public RecordTransformable {
00120 
00121 public:
00122 
00123 //# Friends
00124 
00125 //# Enumerations
00126 
00127 //# Constructors
00128   // Creates an empty holder
00129   MeasureHolder();
00130   // Create from a Measure (copy made)
00131   MeasureHolder(const Measure &in);
00132   // Copy a holder (copy semantics)
00133   MeasureHolder(const MeasureHolder &other);
00134 //# Destructor
00135   ~MeasureHolder();
00136 
00137 //# Operators
00138   // Assignment (copy semantics)
00139   MeasureHolder &operator=(const MeasureHolder &other);
00140 
00141 //# Member Functions
00142   // Check the the MeasureHolder holds the specified Measure type. Return
00143   // True if if does and False otherwise.
00144   // <group>
00145   Bool isEmpty() const;
00146   Bool isMeasure() const;
00147   Bool isMDirection() const;
00148   Bool isMDoppler() const;
00149   Bool isMEpoch() const;
00150   Bool isMFrequency() const;
00151   Bool isMPosition() const;
00152   Bool isMRadialVelocity() const;
00153   Bool isMBaseline() const;
00154   Bool isMuvw() const;
00155   Bool isMEarthMagnetic() const;
00156   // </group>
00157 
00158   // Get a specific Measure from the holder (with lifetime as long 
00159   // as holder exists).
00160   // <thrown>
00161   // <li> AipsError if holder empty
00162   // <li> AipsError if holder contains wrong Measure
00163   // </thrown>
00164   // <group>
00165   const Measure &asMeasure() const;
00166   const MDirection &asMDirection() const;
00167   const MDoppler &asMDoppler() const;
00168   const MEpoch &asMEpoch() const;
00169   const MFrequency &asMFrequency() const;
00170   const MPosition &asMPosition() const;
00171   const MRadialVelocity &asMRadialVelocity() const;
00172   const MBaseline &asMBaseline() const;
00173   const Muvw &asMuvw() const;
00174   const MEarthMagnetic &asMEarthMagnetic() const;
00175   // </group>
00176   // Create a Measure from a record. An error message is generated, and False
00177   // returned if an invalid record is given. A valid record will return True.
00178   // A valid record contains the following fields (any additional fields are
00179   // ignored):
00180   // <ul>
00181   // <li> type = TpString: type of Measure (direction, epoch, etc; case
00182   //     insensitive)
00183   // <li> refer = TpString: reference type of Measure (case insensitive; 
00184   //      enough characters to be unique (e.g. J20, j200, utc, b1950, J2000);
00185   //      unknown reference type will log an error message and translate into
00186   //      the default type for the Measure.
00187   // <li> m0, m1, ... = TpRecord(Quantity): one or more Quantities giving
00188   //      the value(s) for this Measure (e.g. longitude and latitude for a
00189   //      direction). Each quantity can either be a scalar quantity or a
00190   //      Quantum<Vector<Double> >.
00191   // <li> offset = TpRecord(Measure)--optional: an optional offset as a
00192   //      Measure of the same type as the main Measure (e.g. an MEpoch for an
00193   //       MEpoch)
00194   // </ul>
00195   // A Measure can be created from a string. In that case the string
00196   // will only indicate the type of measure (like direction), and will
00197   // create a default measure of that given type. In essence identical
00198   // to the fromType() method. 
00199   // Error messages are postfixed to error.
00200   // <group>
00201   virtual Bool fromRecord(String &error, const RecordInterface &in);
00202   virtual Bool fromString(String &error, const String &in);
00203   // </group>
00204   // Create a record from a Measure. The return will be False and an error
00205   // message generated only if the MeasureHolder does not contain a Measure.
00206   // Error messages are postfixed to error.
00207   virtual Bool toRecord(String &error, RecordInterface &out) const;
00208 
00209   // This version  throws an exception if the conversion cannot
00210   // occur. It is meant for more allow more compact calling code for callers
00211   // that are content with just letting the exception proceed up the call stack
00212   // so they do not have to check a return status. This is, among other things, what
00213   // exceptions are for after all.
00214   // TODO. I'd rather return the RecordInterface, but since RecordInterface is abstract,
00215   // that means returning a pointer that is created internally. That really should be
00216   // done using a smart pointer, but other than our own PtrHolder (which I'd really rather
00217   // not use), auto_ptr is really the only thing that can be used at this point. auto_ptr
00218   // has its own issues and is frowned on by other casacore partners, so I don't want to
00219   // litter casacore code with that. unique_ptr is a much better solution, but as of now
00220   // that is still not available. When it becomes available this issue can be revisited.
00221   virtual void toRecord(RecordInterface& outRecord) const;
00222 
00223 
00224   // Create a default Measure or a record with only a type from a Measure
00225 
00226   // <group>
00227   Bool toType(String &error, RecordInterface &out) const;
00228   Bool fromType(String &error, const RecordInterface &in);
00229   // </group>
00230   // Get identification of record
00231   virtual const String &ident() const;
00232   // Do we write MeasValues to record?
00233   Bool writeMV() const { return convertmv_p; }
00234   // Make a block of n MeasValues
00235   void makeMV(uInt n) { createMV(n); }
00236   // Get number of MeasValue pointers in block
00237   uInt nelements() const { return mvhold_p.nelements(); }
00238   // Set a measvalue at position pos (False if illegal pos)
00239   Bool setMV(uInt pos, const MeasValue &in);
00240   // Get a pointer to a MeasValue (or 0)
00241   MeasValue *getMV(uInt pos) const;
00242 
00243 private:
00244   
00245   //# Data Members
00246   // Pointer to a Measure
00247   PtrHolder<Measure> hold_p;
00248   // Block of pointers to measure values to make a faster interface
00249   Block<MeasValue *> mvhold_p;
00250   // Should the mvhold_p be converted into record?
00251   Bool convertmv_p;
00252   //# Member functions
00253   // Aid for to/from Record, String and Type
00254   // <group>
00255   Bool putType(String &error, RecordInterface &out) const;
00256   Bool getType(String &error, const RecordInterface &in);  
00257   Bool getType(String &error, const String &in);  
00258   // </group>
00259   // Make a MeasValue block of pointers of length n
00260   void createMV(uInt n);
00261 };
00262 
00263 
00264 } //# NAMESPACE CASA - END
00265 
00266 #endif