#ifndef HEPBLOCK_H
#define HEPBLOCK_H

// ----------------------------------------------------------------------
//
// Block.h - class declaration for a Block of Column in an CWN Ntuple
//

// To use:
//   create a HepNtuple manager* M
//   create the HepNtuple*h by M->newHepNtuple(title, id=0)
//   define a block using the one of the method h->block()
//
// Then refine the columns definitions by calls to h->pack(), h->dimensions(),
// etc.
//
// The columns are kept in two container.  One for internal uses only that
// map the column name to a column (a map with type Block::columnsMap).
// One for external use, a list of type Block::columnsVec.  This list is
// ordered first column added first.  It can be sort differently using
// Block::sort(ColumnLess* cmp) [ideally it should actually be a template
// member function.].


#ifdef COMMENT
Codeguard name is HEPBLOCK_H:  Rule is file name starts without the name guard
HEP, so we prepend HEP to the class name.

Mods in development:

7/14/97   	Started this header; including material already known to
		be needed from doing the capture code, and attributes known
		to be needed from when Gao did the transform code.

#endif // COMMENT


#ifdef COMMENT

In this preliminary version of the header for HepNtuple we
don''t know yet how we will want to handle colums of characters (in
HBOOK they have 8 types, CHAR4 thru CHAR32).  This decision won''t seriously
affect the rest of the interface.

#endif /* COMMENT */

#ifndef ZMENVIRONMENT_H
#include "ZMutility/ZMenvironment.h"
#endif

#include "HepTuple/Column.h"

// #include "HepTuple/dummyZMexception.h"
#include "HepTuple/Exceptions.h"

#include "HepTuple/ColumnLess.h"

#include <string>
#ifndef ISOCXX__ISOCXX
  #include "STLUtility/fwd_deque.h"
  #include "STLUtility/fwd_vector.h"
#endif
#include "ZMutility/map"
#include <deque>
#include <vector>


ZM_BEGIN_NAMESPACE( zmht )	/*  namespace zmht  {  */

class HepNtuple;

class Block {

public:

  typedef std::map<std::string,Column*,std::less<std::string> > columnsMap;
  typedef std::STL_DEQUE(Column*) columnsVec;
  // this should have been a vector ... but G++ vectors don't work
  // with sort.

  // ************************************ //
  // ****** Constructor/Destructor ****** //
  // ************************************ //

  Block(HepNtuple* owner, const std::string& Name, bool isCaseSensitive);
  Block(HepNtuple* owner, const std::string& Name, Column* newCol, bool isCaseSensitive);

  Block *duplicate(HepNtuple* newOwner) const;
  // Create a duplicate of the block AND its columns
  // but without any data.

  ~Block();

  // *************************************** //
  // ****** Method regarding columns  ****** //
  // *************************************** //

  bool addColumn(Column* newCol);
  // this throws an exception if the column is locked.

  int nColumns() const;
  const columnsVec& columns() const;

  Column* findColumn(const std::string& colName) const;
  // return the column name colName.  return NULL
  // if there is no column with this name in the block.

  Column* findColumn(int ColNumber) const;
  // return the ColNumber'th columns

  // ********************************** //
  // ****** Information on block ****** //
  // ********************************** //

  std::string format() const;
  std::string name() const;
  bool isLockedNewColumn() const;
  bool isCaptured() const;
  // return true if the block has been captured as whole
  // (through Block::capture()) or if ALL columns had been captured.

  bool hasSomeDestination() const;
  // return true if at least one of the column has a destination set.

  // ************************** //
  // ****** Modify block ****** //
  // ************************** //

  void sortColumn(ColumnLess* cmp);
  // Sort the columns according to the comparator cmp

  bool lockNewColumn();
  bool allowNewColumn();
  // lock/unlock the addition of new columns. (and return previous status).
  // allowNewColumn will delete the memory allocated by capturedData()
  // Unlocking the Block after it has been booked result in an exception

  void book();
  bool isBooked();
  // inform the block that it has been booked.

  void clear();
  // clear the status of the block and all colums!
  bool capture();
  // Capture all columns (via column::captureDesignatedValues() )
  // that have not been capture yet. Can only be call once unless
  // cleared.

  std::string::size_type capturedDataSize() const;
  // return the size of the array containing all captured data

  void* capturedData(std::string::size_type prePadding = 0);
  // return a pointer an array containing the captured data for all the
  // columns. This has the effect of locking the block against no columns
  // additions.
  // The extra number of bytes indicated by prePadding will be allocated.
  // but the block will place then at the beginning of the array and will NOT
  // use them.  The value returned by capturedDataSize is the actual start of
  // the data (i.e. after the pre-padding.

  void* dataArray(std::string::size_type prePadding = 0);
  // return a pointer to an array that can contain the data for all the
  // column of the block. prePadding is the same as capturedData

  bool read();
  // transfer the value of all columns to their set destinations (or
  // methods).

  bool load();
  // transfer the value of all columns from the block dataArray to the value holder
  // in the columns.

  //generate the HBOOK chForm (a character string) from an
  // array of ColumnAttribs or a HepAList of Column
  std::string AttribsToChform(const int nColumns,
			 const ColumnAttribs* AryofColumnAttribs ) const;
  std::string AttribsToChform(std::STL_VECTOR(Column*) listOfColumns ) const;
  std::string AttribsToChform(std::STL_DEQUE(Column*) listOfColumns ) const;
  std::string AttribsToChform(std::STL_VECTOR(ColumnAttribs*) listOfColumnsAttr ) const;

private:
  columnsMap _columns;
  columnsVec _columnsList;

  std::string _name;
  HepNtuple* _hepTuple;
  bool _isCaseSensitive;

  mutable std::string _format;
  mutable bool _formatUptodate;

  bool _lockNoNewColumn;
  bool _captured;
  bool _booked;

  char* _capturedArray;
  // this contains a copy of all captured data.
  std::string::size_type _prePadding;
  // the memory allocated for _capturedArray starts
  // at _caputuredArray - _prePadding

}; /* Block */


ZM_END_NAMESPACE( zmht )	/*  }  // namespace zmht  */

#include "HepTuple/Block.icc"

#endif // Code Guard HEPBLOCK_H
