VSCEngine.h

Classes

VSCEngine -- Base virtual column for a scalar column with any type (full description)

class VSCEngine : public VirtualColumnEngine, public VirtualScalarColumn<T>

Interface

Public Members
VSCEngine()
VSCEngine (const String& sourceColumnName)
~VSCEngine()
String dataManagerType() const
Bool canAddRow() const
Bool canRemoveRow() const
const String& sourceColumnName() const
Protected Members
VSCEngine (const VSCEngine<T>&)
Private Members
VSCEngine<T>& operator= (const VSCEngine<T>&)
void addRow (uInt nrrow)
void removeRow (uInt rownr)
Bool isWritable() const
DataManagerColumn* makeScalarColumn (const String& columnName, int dataType, const String& dataTypeID)

Description

Prerequisite

Etymology

VSCEngine stands for Virtual Scalar Column Engine, i.e. a class handling a virtual table column containing scalar values.

Synopsis

VSCEngine is a base virtual column engine to handle a column with an arbitrary type. Data of columns with standard data types can directly be stored in a Table using a storage manager, but data of column with non-standard types have to be stored in another way. The way to do this is to split the object with the non-standard type into its individual elements, which are subsequently put into the appropriate columns.

A virtual column engine has to be implemented for each non-standard data type, which has to be stored in a table. This engine has to get and put the individual parts the object. VSCEngine is the base class for such engines, so the actual engine quite simple to implement. The example shows the implementation of an engine AVSCEngine handling a data type A.

In principle the name of the engine class is free, but it is strongly recommended to use the name VSCEngine, where VSC stands for Virtual Scalar Column (e.g. AVSCEngine for class A). In this way the default data manager name supplied by the class and by class ScalarColumnDesc can be used.

Example

This example shows the implementation of an engine class AVSCEngine, which stores the data of a class A. The data objects A are stored in a column called the source column. The user has to associate two target columns with it. The engine stores the data parts x and y in the target columns. The names of the target columns are stored as keywords in the source column. In this way the engine can reconstruct itself when the table is read back.

In the example all AVSCEngine functions are shown inline, but they should be implemented out-of-line in a separate .cc file.

  //# AVSCEngine.h: Example virtual column engine to handle data type A

  #if !defined(AIPS_AVSCENGINE_H)
  #define AIPS_AVSCENGINE_H

  //# Includes
  #include <aips/Tables/VSCEngine.h>
  #include <aips/Tables/ScalarColumn.h>

  // Define the class A.
  class A
  {
  public:
      A(): x_p(0), y_p(0) {}
      A(Int x, float y) : x_p(x), y_p(y) {}
      A(const A& that): x_p(that.x_p), y_p(that.y_p) {}
      static String dataTypeId()
          { return "A"; }
      Int x() const
          { return x_p; }
      float y() const
          { return y_p; }
      Int& x()
          { return x_p; }
      float& y()
          { return y_p; }
      int operator== (const A& that) const
          { return x_p==that.x_p && y_p==that.y_p; }
      int operator< (const A& that) const
          { return x_p<that.x_p || (x_p==that.x_p && y_p<that.y_p); }
  private:
      Int   x_p;
      float y_p;
  };

  // Now define the engine to handle objects of type A.
  class AVSCEngine : public VSCEngine<A>
  {
  public:

      // The default constructor is required for reconstruction of the
      // engine when a table is read back.
      AVSCEngine()
      {}

      // Construct the engine for the given source column and storing
      // the result in the given target columns for the data members
      // x and y of class A.
      AVSCEngine (const String& sourceColumnName,
                  const String& xTargetColumnName,
                  const String& yTargetColumnname)
      : VSCEngine<A>  (sourceColumnName),
        xTargetName_p (xTargetColumnName),
        yTargetName_p (yTargetColumnName)
      {}

      // Destructor is mandatory.
      virtual ~AVSCEngine()
      {}

      // Clone the object.
      virtual DataManager* clone() const
      {
          DataManager* dmPtr = new AVSCEngine (sourceColumnName(),
					 xTargetName_p, yTargetName_p);
          if (dmPtr == 0) {
              throw (AllocError ("AVSCEngine::clone()", 1));
          }
          return dmPtr;
      }

      // Store the target column names in the source column keywords.
      virtual void create (uInt)
      {
          TableColumn src (table(), sourceColumnName());
          src.keywordSet().keysString()("_xTargetName") = xTargetName_p;
          src.keywordSet().keysString()("_yTargetName") = yTargetName_p;
      }

      // Prepare the engine by allocating column objects
      // for the target columns.
      virtual void prepare()
      {
          ROTableColumn src (table(), sourceColumnName());
          xTargetName_p = src.keywordSet().asString ("_xTargetName");
          yTargetName_p = src.keywordSet().asString ("_yTargetName");
          rocolx.attach (table(), xTargetName_p);
          rocoly.attach (table(), yTargetName_p);
          if (table().isWritable()) {
              colx.attach (table(), xTargetName_p);
              coly.attach (table(), yTargetName_p);
          }
      }

      // Get the data from a row.
      virtual void get (uInt rownr, A& value)
      {
          rocolx.get (rownr, value.x());
          rocoly.get (rownr, value.y());
      }

      // Put the data in a row.
      virtual void put (uInt rownr, const A& value)
      {
          colx.put (rownr, value.x());
          coly.put (rownr, value.y());
      }

      // Register the class name and the static makeObject "constructor".
      // This will make the engine known to the table system.
      static void registerClass()
      {
          DataManager::registerCtor ("AVSCEngine", makeObject);
      }

  private:
      // Copy constructor is only used by clone().
      // (so it is made private).
      AVSCEngine (const AVSCEngine&)
      : VSCEngine<A>  (that),
        xTargetName_p (that.xTargetName_p),
        yTargetName_p (that.yTargetName_p)
      {}

      // Assignment is not needed and therefore forbidden
      // (so it is made private and is not implemented).
      AVSCEngine& operator= (const AVSCEngine&);


      // The target column names.
      String xTargetName_p;
      String yTargetName_p;
      // Objects for the target columns.
      ScalarColumn<Int>     colx;       // used by put
      ROScalarColumn<Int>   rocolx;     // used by get
      ScalarColumn<float>   coly;       // used by put
      ROScalarColumn<float> rocoly;     // used by get

  public:
      // Define the "constructor" to construct this engine when a
      // table is read back.
      // This "constructor" has to be registered by the user of the engine.
      // Function registerClass() is doing that.
      static DataManager* makeObject (const String& dataManagerType)
      {
          DataManager* dmPtr = new AVSCEngine();
          if (dmPtr == 0) {
              throw (AllocError ("AVSCEngine::makeObject()", 1));
          }
          return dmPtr;
      }
  };

  #endif

User code using this engine to create a new table could look like:

   // Register the engine.
   // This is not needed if the engine is registered as part
   // of the general DataManager::registerAllCtor function.
   AVSCEngine::registerClass();
   // Create the table description.
   TableDesc td;
   td.addColumn (ScalarColumnDesc<A>("source"));
   td.addColumn (ScalarColumnDesc<Int>("xTarget"));
   td.addColumn (ScalarColumnDesc<Int>("yTarget"));
   SetupNewTable setup ("table.name", td, Table::New);
   // Define the engine for column "source".
   AVSCEngine engine ("source", "xTarget", "yTarget");
   Table tab (setup, 10);
   // Put data into column "source".
   ScalarColumn<A> col (tab, "source");
   for (uInt i=0; i<10; i++) {
       col.put (i, someA);     // writes indirectly xTarget and yTarget
   }

Motivation

This class makes it easier for the user to implement the engine. It supplies several default functions.

Template Type Argument Requirements (T)

Member Description

VSCEngine()

The default constructor is required for reconstruction of the engine when a table is read back. It is also used to construct an engine, which does not check the source column name.

VSCEngine (const String& sourceColumnName)

Construct an engine to handle a column with an arbitrary data type. Later it will check if the source column name is correct.

~VSCEngine()

Destructor is mandatory.

String dataManagerType() const

Return the data manager type name. This defaults to the data type ID followed by VSCEngine (meaning Virtual Scalar Column Engine).

Bool canAddRow() const

Adding rows is possible for this engine.

Bool canRemoveRow() const

Deleting rows is possible for this engine.

const String& sourceColumnName() const

Get the name of the source column.

VSCEngine (const VSCEngine<T>&)

Copy constructor is only used by clone(). (so it is made protected).

VSCEngine<T>& operator= (const VSCEngine<T>&)

Assignment is not needed and therefore forbidden (so it is made private).

void addRow (uInt nrrow)

Add a row. By default this is not doing anything.

void removeRow (uInt rownr)

Delete a row. By default this is not doing anything.

Bool isWritable() const

The column is in principle writable. This does not mean it is actually writable, because that depends on the fact if the table is writable.

DataManagerColumn* makeScalarColumn (const String& columnName, int dataType, const String& dataTypeID)

Create the column object for the scalar column in this engine. It will check if the given column name matches the source column name. This assures that the engine is bound to the correct column.