/*
FILE:     CifDataBlock.h
*/
/*
VERSION:  4
*/
/*
DATE:     6/17/2002
*/
/*
  Comments and Questions to: sw-help@rcsb.rutgers.edu
*/
/*
COPYRIGHT 1999-2002 Rutgers - The State University of New Jersey

This software is provided WITHOUT WARRANTY OF MERCHANTABILITY OR
FITNESS FOR A PARTICULAR PURPOSE OR ANY OTHER WARRANTY, EXPRESS OR
IMPLIED.  RUTGERS MAKE NO REPRESENTATION OR WARRANTY THAT THE
SOFTWARE WILL NOT INFRINGE ANY PATENT, COPYRIGHT OR OTHER
PROPRIETARY RIGHT.

The user of this software shall indemnify, hold harmless and defend
Rutgers, its governors, trustees, officers, employees, students,
agents and the authors against any and all claims, suits,
losses, liabilities, damages, costs, fees, and expenses including
reasonable attorneys' fees resulting from or arising out of the
use of this software.  This indemnification shall include, but is
not limited to, any and all claims alleging products liability.
*/
/*
               PDB SOFTWARE LICENSE AGREEMENT

BY CLICKING THE ACCEPTANCE BUTTON OR INSTALLING OR USING 
THIS "SOFTWARE, THE INDIVIDUAL OR ENTITY LICENSING THE  
SOFTWARE ("LICENSEE") IS CONSENTING TO BE BOUND BY AND IS 
BECOMING A PARTY TO THIS AGREEMENT.  IF LICENSEE DOES NOT 
AGREE TO ALL OF THE TERMS OF THIS AGREEMENT
THE LICENSEE MUST NOT INSTALL OR USE THE SOFTWARE.

1. LICENSE AGREEMENT

This is a license between you ("Licensee") and the Protein Data Bank (PDB) 
at Rutgers, The State University of New Jersey (hereafter referred to 
as "RUTGERS").   The software is owned by RUTGERS and protected by 
copyright laws, and some elements are protected by laws governing 
trademarks, trade dress and trade secrets, and may be protected by 
patent laws. 

2. LICENSE GRANT

RUTGERS grants you, and you hereby accept, non-exclusive, royalty-free 
perpetual license to install, use, modify, prepare derivative works, 
incorporate into other computer software, and distribute in binary 
and source code format, or any derivative work thereof, together with 
any associated media, printed materials, and on-line or electronic 
documentation (if any) provided by RUTGERS (collectively, the "SOFTWARE"), 
subject to the following terms and conditions: (i) any distribution 
of the SOFTWARE shall bind the receiver to the terms and conditions 
of this Agreement; (ii) any distribution of the SOFTWARE in modified 
form shall clearly state that the SOFTWARE has been modified from 
the version originally obtained from RUTGERS.  

2. COPYRIGHT; RETENTION OF RIGHTS.  

The above license grant is conditioned on the following: (i) you must 
reproduce all copyright notices and other proprietary notices on any 
copies of the SOFTWARE and you must not remove such notices; (ii) in 
the event you compile the SOFTWARE, you will include the copyright 
notice with the binary in such a manner as to allow it to be easily 
viewable; (iii) if you incorporate the SOFTWARE into other code, you 
must provide notice that the code contains the SOFTWARE and include 
a copy of the copyright notices and other proprietary notices.  All 
copies of the SOFTWARE shall be subject to the terms of this Agreement.  

3. NO MAINTENANCE OR SUPPORT; TREATMENT OF ENHANCEMENTS 

RUTGERS is under no obligation whatsoever to: (i) provide maintenance 
or support for the SOFTWARE; or (ii) to notify you of bug fixes, patches, 
or upgrades to the features, functionality or performance of the 
SOFTWARE ("Enhancements") (if any), whether developed by RUTGERS 
or third parties.  If, in its sole discretion, RUTGERS makes an 
Enhancement available to you and RUTGERS does not separately enter 
into a written license agreement with you relating to such bug fix, 
patch or upgrade, then it shall be deemed incorporated into the SOFTWARE 
and subject to this Agreement. You are under no obligation whatsoever 
to provide any Enhancements to RUTGERS or the public that you may 
develop over time; however, if you choose to provide your Enhancements 
to RUTGERS, or if you choose to otherwise publish or distribute your 
Enhancements, in source code form without contemporaneously requiring 
end users or RUTGERS to enter into a separate written license agreement 
for such Enhancements, then you hereby grant RUTGERS a non-exclusive,
royalty-free perpetual license to install, use, modify, prepare
derivative works, incorporate into the SOFTWARE or other computer
software, distribute, and sublicense your Enhancements or derivative
works thereof, in binary and source code form.

4. FEES.  There is no license fee for the SOFTWARE.  If Licensee
wishes to receive the SOFTWARE on media, there may be a small charge
for the media and for shipping and handling.  Licensee is
responsible for any and all taxes.

5. TERMINATION.  Without prejudice to any other rights, Licensor
may terminate this Agreement if Licensee breaches any of its terms
and conditions.  Upon termination, Licensee shall destroy all
copies of the SOFTWARE.

6. PROPRIETARY RIGHTS.  Title, ownership rights, and intellectual
property rights in the Product shall remain with RUTGERS.  Licensee 
acknowledges such ownership and intellectual property rights and will 
not take any action to jeopardize, limit or interfere in any manner 
with RUTGERS' ownership of or rights with respect to the SOFTWARE.  
The SOFTWARE is protected by copyright and other intellectual 
property laws and by international treaties.  Title and related 
rights in the content accessed through the SOFTWARE is the property 
of the applicable content owner and is protected by applicable law.  
The license granted under this Agreement gives Licensee no rights to such
content.

7. DISCLAIMER OF WARRANTY.  THE SOFTWARE IS PROVIDED FREE OF 
CHARGE, AND, THEREFORE, ON AN "AS IS" BASIS, WITHOUT WARRANTY OF 
ANY KIND, INCLUDING WITHOUT LIMITATION THE WARRANTIES THAT IT 
IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE 
OR NON-INFRINGING.  THE ENTIRE RISK AS TO THE QUALITY AND 
PERFORMANCE OF THE SOFTWARE IS BORNE BY LICENSEE.  SHOULD THE 
SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, THE LICENSEE AND NOT 
LICENSOR ASSUMES THE ENTIRE COST OF ANY SERVICE AND REPAIR.  
THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF 
THIS AGREEMENT.  NO USE OF THE PRODUCT IS AUTHORIZED HEREUNDER 
EXCEPT UNDER THIS DISCLAIMER.

8. LIMITATION OF LIABILITY.  TO THE MAXIMUM EXTENT PERMITTED BY
APPLICABLE LAW,  IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY 
INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 
OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE, INCLUDING, 
WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK 
STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL 
OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF ADVISED OF THE
POSSIBILITY THEREOF. 
*/
/* **************************************************************** *

  PURPOSE:      This file contains the definitions of class
                CifDataBlock

 * **************************************************************** */

#ifndef H_CIFDATABLOCK
#define H_CIFDATABLOCK


#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <malloc.h>

#include "CifString.h"
#include "CifDefs.h"
#include "CifErrorCodes.h"
#include "CifFileIo.h"
#include "CifAnon.h"
#include "CifJoin.h"
#include "CifAlias.h"
#include "CifNameAttributes.h"
#include "CifItemValue.h"
#include "CifDataItem.h"
#include "CifCategory.h"
#include "ReVarCifArray.h"

extern "C" 
{
  /* regex functions */

//  char *re_comp(const char*);
//  int re_exec(const char *);
//  int re_match_whole(const char *);
}


class CifDataBlock
{
  friend class CifFileIo;
  friend class CifFile;
  friend class CifCategory;
 private:
  int       _verbose;
  int       _dictionaryIndex;
  long      _fileOffset;
  CifString _dataBlockName;
  CifString _dictionaryName;
  CifString _dictionaryVersion;
  CifString _fileName; 
  CifNameAttributes              _nameAttributes; 
  ReVarCifArray <CifString>      _constructs; /* decoded construct of item_type_list */
  ReVarCifArray <CifString>      _errors;     /* error messages */
  ReVarCifArray <CifString>      _warnings;   /* warning message*/
  ReVarCifArray <CifCategory>    _categories; 


  int GetInsertIndex(const char *categoryName);
  int GetInsertIndex(const CifString categoryName);
  void InsertRowsFromFile(CifDataBlock *dic,
			  const int verify,
			  const int lineno,
			  const long offset,
			  CifCategory *newdata,
			  const CifString *dataBlockName = NULL, 
			  const CifString *categoryName = NULL, 
			  const CifString *itemName = NULL);
  void InsertRows(CifDataBlock *dic, CifCategory *newdata, 
		  const int verify = TRUE, 
		  const int lineno = -1);

  void CheckIdAndItemColumns(CifDataBlock *dic);
  void BuildParentsChildrenLinkList(CifDataBlock *dic);
  void BuildDependentItems(CifDataBlock *dic);
  void BuildRelatedItems(CifDataBlock *dic);
  void BuildNameAttributes();
  void GetNameStructureInfo(CifString itemName,
			    ReVarCifArray <CifString> *parents,
			    int insertpoint);
  void GetNameItemInfo(CifString itemName,
		       ReVarCifArray <CifString> *parents,
		       int insertpoint);
  void GetNameItemDefaultValue(CifString itemName,
		       int insertpoint);
  void GetNameItemAliasName(CifString itemName,
			    int insertpoint);
  void AddLinkParentsAndChildren(CifDataBlock *dic, int categoryIndex, int itemIndex);
  void CheckParentsChildrenRelation();
  int  CheckChildrenItemValueBeforeDelete(const int categoryIndex, 
				      const int itemIndex, const int rowIndex,
				      const int vertification_flag);

  int  GetIdOrItemKeyword(const CifString categoryName, const char *tmpkeyword, 
			  CifString *itemName);
  int  GetMandatoryCode(CifString item_full_name, CifItemValue **mandatory_itemValue);
  void GetDDLItemInfo(CifDataBlock *dic, const int verify);
  void GetItemStructureInfo(CifDataItem *item, CifString categoryName);
  void GetItemInfo(CifDataItem *item);
  void RefineDataBlock(CifDataBlock *dic, const int verify);

  void CheckDataBlock(CifDataBlock *dic, const int fromFile);

  int  BuildAliasBlock(CifFileIo *ciffile);
  void Merge(CifDataBlock *dic, CifDataBlock *block);
  void DeleteDuplicateRows();
  void BuildItemTypeListConstruct();


 public:
  void SetVerboseState(const int newState);
  CifCategory *GetItemAttribute(const CifItemValue *match_itemValue,
				const CifString matchedItemKeyword, 
				const CifString categoryName,
				const CifString itemKeyword);

  ReVarCifArray <CifString> *BuildCategoryKeys(CifString categoryName);
  ReVarCifArray <CifString> *GetCategoryKeys(const CifString categoryName);
  ReVarCifArray <CifString> *GetCategoryKeys(const int categoryIndex);

  ReVarCifArray <CifItemValue> *GetColumnItemValues(const CifString categoryName, const CifString itemName);
  ReVarCifArray <CifItemValue> *GetColumnItemValues(const int categoryIndex, const int itemIndex);

  void SetDatablockName(const char *dataBlockName);
  CifDataBlock () {_verbose=TRUE;};
  CifDataBlock (const CifDataBlock &old) ;
  ~CifDataBlock () { DeleteElement();}
  void DeleteElement();
  CifDataBlock &operator=(const CifDataBlock &old) { return Copy(old);}
  CifDataBlock &Copy (const CifDataBlock &old) ;
  void Print() const;
  void PrintDetails() const;
  void PrintTable() const;
  void FreeExtra();

  int CountCategories() { return _categories.Length(); }
  int CountItem(const int categoryIndex);
  int CountItem(const CifString categoryName);
  int CountRows(const int categoryIndex);

  CifString *GetCategoryName(const int categoryIndex) ;
  CifString *GetItemKeyword(const int categoryIndex, const int itemIndex);
  CifString *GetItemName(const int categoryIndex, const int itemIndex);
  CifString *GetItemAliasName(const int categoryIndex, const int itemIndex,
			   const CifString *dictionary = NULL, const CifString *version = NULL);

  int GetItemIndex(const int categoryIndex, const char *itemKeyword);
  CifString *GetItemNameFromAlias(CifString *aliasName, CifString *itemName);

  int GetItemDataType(const int categoryIndex, const int itemIndex) ;
  int GetItemDataType(const CifString categoryName, const CifString itemName);
  int GetItemCaseSensitivity(const int categoryIndex, const int item_no);
  int GetItemCaseSensitivity(const CifString categoryIndex, const CifString item_no);
  int GetItemStructureIndex(const int categoryIndex, const int itemIndex) ;
  int GetItemStructureIndex(const CifString categoryName, const CifString itemName);
  int GetItemStructureNumValue(const int categoryIndex, const int itemIndex) ;
  int GetItemStructureNumValue(const CifString categoryName, const CifString itemName);
  int GetItemStructureDimension(const int categoryIndex, const int itemIndex) ;
  int GetItemStructureDimension(const CifString categoryName, const CifString itemName);
  int GetItemStructureOrganization(const int categoryIndex, const int itemIndex) ;
  int GetItemStructureOrganization(const CifString categoryName, const CifString itemName);

  int CountWarnings() { return _warnings.Length(); }
  int CountErrors() { return _errors.Length(); }
  ReVarCifArray <CifString> *GetErrors() { return &_errors;} 
  ReVarCifArray <CifString> *GetWarnings(){ return &_warnings;} 
  void FreeWarnings() {_warnings.DeleteAt(0, _warnings.Length());}
  void FreeErrors() { _errors.DeleteAt(0, _errors.Length());}
  CifString *GetWarning(const int warningIndex);
  CifString *GetError(const int errorIndex);
  void FreeWarning(const int warningIndex);
  void FreeError(const int errorIndex);
  
  CifItemValue *GetItemDefaultValue(const CifString name);
  CifItemValue *GetItemDefaultValue(const int category, const int item);
  CifItemValue *GetItemDefaultValue(const CifString category, const CifString item);

  CifString *GetItemPrimitiveCode(const int categoryIndex,
			       const int itemIndex);
  CifString *GetItemPrimitiveCode(const CifString category,
			       const CifString item);
  CifString *GetItemDataTypeCode(const int categoryIndex, const int itemIndex);
  CifString *GetItemDataTypeCode(const CifString category, const CifString item);
  int    GetDataBlockDictionaryIndex() { return _dictionaryIndex;}
  CifString *GetDataBlockName() { return &_dataBlockName;}
  CifString *GetFileName() { return &_fileName; }
  long   GetFileOffset() { return _fileOffset; }
  long   GetItemFileOffset(const char *name);
  long   GetItemFileOffset(const CifString name);


  int GetIndex(const char *relation_name);
  int GetIndex(const CifString groupname);

  CifCategoryIndex *GetTableIndex(const char *relation, const char *itemName);
  CifCategoryIndex *GetTableIndex(const CifString relation, const CifString itemName);
  CifCategoryIndex *GetTableIndex(const CifString name);
  CifCategoryIndex *GetTableIndex(const char *name);

  void ReadDatablock(CifFileIo *ciffile, CifDataBlock *global_information,
		     CifDataBlock *dic, const int verify);

  void WriteDataBlock(CifFileIo *ciffile, const int writeComment = TRUE, 
		      const int esdFlag = TRUE,
		      const CifString *dictionary = NULL,
		      const CifString *version = NULL,
		      CifDataBlock *dic = NULL);

  void PermanentWrite(FILE *fp);
  void PermanentRead(FILE *fp);

  ReVarCifArray <CifCategoryIndex> *GetLinkParents(const int categoryIndex, 
					       const int itemIndex);
  ReVarCifArray <CifCategoryIndex> *GetLinkParents(const CifString categoryName,
					       const CifString itemKeyword);
  ReVarCifArray <CifCategoryIndex> *GetLinkChildren(const int categoryIndex, 
						const int itemIndex);
  ReVarCifArray <CifCategoryIndex> *GetLinkChildren(const CifString categoryName,
						const CifString itemKeyword);

  ReVarCifArray <CifCategoryIndex> *GetDependentItems(const int categoryIndex, 
						  const int itemIndex);
  ReVarCifArray <CifCategoryIndex> *GetDependentItems(const CifString categoryName, 
						  const CifString itemName);
  ReVarCifArray <CifRelatedItem> *GetRelatedItems(const int categoryIndex, 
						 const int itemIndex);
  ReVarCifArray <CifRelatedItem> *GetRelatedItems(const CifString categoryName, 
						 const CifString itemName);

  int GetItemValue(CifItemValue **itemValue, const int categoryIndex, const int itemIndex, 
	       const int rowIndex);
  int GetItemValue(CifString **itemValue, const int categoryIndex, const int itemIndex,
	       const int rowIndex);
  int GetItemValue(CifItemValue **itemValue, const CifString categoryName, 
	       const CifString itemKeyword, const int rowIndex);
  int GetItemValue(CifString **itemValue, const CifString categoryName, 
	       const CifString itemKeyword, const int rowIndex);


  int UpdateItemValue(CifDataBlock *dic, CifItemValue *itemValue, const int categoryIndex, 
		  const int itemIndex, const int rowIndex,
		  const int verify);
  int UpdateItemValue(CifDataBlock *dic, CifItemValue *itemValue, const CifString categoryName, 
		  const CifString itemKeyword, const int rowIndex, 
		  const int verify);

  int InsertItemValue(CifDataBlock *dic, CifItemValue *itemValue, const int categoryIndex, 
		  const int itemIndex, const int rowIndex, 
		  const int verify, int lineNo = -1);
  int InsertItemValue(CifDataBlock *dic, CifItemValue *itemValue, const CifString categoryName, 
		  const CifString itemKeyword, const int rowIndex, 
		  const int verify, int lineNo = -1);

  int DeleteItemValue(const int categoryIndex, const int itemIndex, 
		  const int rowIndex, const int verify);
  int DeleteItemValue(const CifString categoryName, const CifString itemKeyword, 
		  const int rowIndex, const int verify);

  CifString* GetDictionaryVersion();
  CifString* GetDictionaryTitle();

  ReVarCifArray <CifString> *GetParentsName(CifString name);
  ReVarCifArray <CifString> *GetChildrenName(CifString name);
  CifCategory *JoinTable(CifJoin *join);
  CifCategory *Join(CifJoin *join);

  int ItemValueConstructCheck(CifDataBlock *dic, CifItemValue *itemValue, 
			      const int categoryIndex, const int itemIndex, 
			      const int lineNo);
  int VerifyItemValue(CifDataBlock *dic, CifItemValue *itemValue, 
		  const int categoryIndex, const int itemIndex, const int lineNo);

  int ItemValueExist(const CifItemValue *childItemValue, const int childCategoryIndex, 
		 const int childItemIndex);
  int ItemValueExist(const CifItemValue *childItemValue, const CifString categoryName, 
		 const CifString itemName);
  int ItemValueExist(const CifItemValue *childItemValue, const char *categoryName, 
		 const char *itemName);


  int ItemValueInParents(const CifItemValue *itemValue, const int categoryIndex, 
			 const int itemIndex);
  int ItemValueInEnumerationList(CifDataBlock *dic, ReVarCifArray <CifString> *parents,
				 const CifItemValue *itemValue,
				 const int categoryIndex, const int itemIndex,
				 const int lineNo);
  int ItemValueInItemRange(CifDataBlock *dic, ReVarCifArray <CifString> *parents,
			   const double itemValue,
			   const int categoryIndex, const int itemIndex,
			   const int lineNo);
  CifCategory *AddCategory(CifDataBlock *dic, const CifString categoryName);
  CifCategory *AddCategory(CifDataBlock *dic, const char *categoryName); 
  CifDataItem* AddDataItem(CifDataBlock *dic, const int categoryIndex,
			     const CifString itemName);
  CifDataItem* AddDataItem(CifDataBlock *dic, const int categoryIndex,
			     const char *itemName);
  int AddRow(const int categoryIndex);
  void ErrorMessage(const int errorMessage, 
		       const int lineNo, const char *message);

  void ErrorMessage(const int errorMessage, 
		       const int lineNo, const CifString message);
};


inline int CifDataBlock::GetIndex(const CifString item)
{
  return GetIndex(item.Text());
}

inline void CifDataBlock::SetVerboseState(const int newState)
{
  _verbose = newState;
}

inline long CifDataBlock::GetItemFileOffset(const CifString name)
{ 
   return GetItemFileOffset(name.Text());
}
inline int CifDataBlock::ItemValueExist(const CifItemValue *childItemValue, 
				     const CifString categoryName, const CifString itemName)
{
  return ItemValueExist(childItemValue, categoryName.Text(), itemName.Text());
}
inline  ReVarCifArray <CifString> *CifDataBlock::GetCategoryKeys(const CifString categoryName)
{
  int categoryIndex;
  categoryIndex = GetIndex(categoryName);
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return (ReVarCifArray <CifString> *) NULL;
  else return _categories[categoryIndex].GetCategoryKeys();
}
inline  ReVarCifArray <CifString> *CifDataBlock::GetCategoryKeys(const int categoryIndex)
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return (ReVarCifArray <CifString> *) NULL;
  else return _categories[categoryIndex].GetCategoryKeys();
}
inline CifString *CifDataBlock::GetCategoryName(const int categoryIndex)
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return (CifString *) NULL;
  else return _categories[categoryIndex].GetCategoryName();
}
inline CifString *CifDataBlock::GetItemKeyword(const int categoryIndex, const int itemIndex) 
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  (CifString *) NULL;
  else return _categories[categoryIndex].GetItemKeyword(itemIndex);
}
inline int CifDataBlock::GetItemIndex(const int categoryIndex, const char *itemKeyword) 
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  -1;
  else return _categories[categoryIndex].GetIndex(itemKeyword);
}
inline CifString *CifDataBlock::GetItemName(const int categoryIndex, const int itemIndex) 
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  (CifString *) NULL;
  else return _categories[categoryIndex].GetItemName(itemIndex);
}
inline int CifDataBlock::GetItemCaseSensitivity(const int categoryIndex, const int itemIndex)
// ----------------------------------------------------------------------
//   GetItemValue() Gets itemValue from itemValues array
// --------------------------------------------------------------------- 
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemCaseSensitivity(itemIndex);
}
inline int CifDataBlock::GetItemCaseSensitivity(const CifString categoryName, 
					       const CifString itemName) 
{
  int categoryIndex;

  categoryIndex = GetIndex(categoryName);
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemCaseSensitivity(itemName);
}

inline int CifDataBlock::GetItemDataType(const int categoryIndex, const int itemIndex) 
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemDataType(itemIndex);
}
inline int CifDataBlock::GetItemDataType(const CifString categoryName, 
					  const CifString itemName) 
{
  int categoryIndex;

  categoryIndex = GetIndex(categoryName);

  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemDataType(itemName);
}
inline int CifDataBlock::GetItemStructureIndex(const int categoryIndex, const int itemIndex) 
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemStructureIndex(itemIndex);
}
inline int CifDataBlock::GetItemStructureIndex(const CifString categoryName, 
					  const CifString itemName) 
{
  int categoryIndex;

  categoryIndex = GetIndex(categoryName);
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemStructureIndex(itemName);
}
inline int CifDataBlock::GetItemStructureNumValue(const int categoryIndex, const int itemIndex) 
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemStructureNumValue(itemIndex);
}
inline int CifDataBlock::GetItemStructureNumValue(const CifString categoryName, 
					  const CifString itemName) 
{
  int categoryIndex;

  categoryIndex = GetIndex(categoryName);
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemStructureNumValue(itemName);
}
inline int CifDataBlock::GetItemStructureDimension(const int categoryIndex, const int itemIndex) 
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemStructureDimension(itemIndex);
}
inline int CifDataBlock::GetItemStructureDimension(const CifString categoryName, 
					  const CifString itemName) 
{
  int categoryIndex;

  categoryIndex = GetIndex(categoryName);
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemStructureDimension(itemName);
}
inline int CifDataBlock::GetItemStructureOrganization(const int categoryIndex, const int itemIndex) 
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemStructureOrganization(itemIndex);
}
inline int CifDataBlock::GetItemStructureOrganization(const CifString categoryName, 
					  const CifString itemName) 
{
  int categoryIndex;

  categoryIndex = GetIndex(categoryName);
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return CIF_CATEGORY_NOT_EXIST  ;
  else return _categories[categoryIndex].GetItemStructureOrganization(itemName);
}
inline int CifDataBlock::CountRows(const int categoryIndex)
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return 0;
  else return _categories[categoryIndex].CountRows();
}

inline CifItemValue *CifDataBlock::GetItemDefaultValue(const int categoryIndex, const int itemIndex)
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return NULL;
  else
    return _categories[categoryIndex].GetItemDefaultValue(itemIndex);
}
inline CifItemValue *CifDataBlock::GetItemDefaultValue(const CifString category, const CifString item)
{
  int categoryIndex;
  categoryIndex = GetIndex(category);
  if (categoryIndex != -1)
    return _categories[categoryIndex].GetItemDefaultValue(item);
  else return NULL;
}
inline CifString *CifDataBlock::GetItemDataTypeCode(const int categoryIndex, const int itemIndex)
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return NULL;
  else
    return _categories[categoryIndex].GetItemDataTypeCode(itemIndex);
}
inline CifString *CifDataBlock::GetItemDataTypeCode(const CifString category, const CifString item)
{
  int categoryIndex;
  categoryIndex = GetIndex(category);
  if (categoryIndex != -1)
    return _categories[categoryIndex].GetItemDataTypeCode(item);
  else return NULL;
}
inline CifString *CifDataBlock::GetItemPrimitiveCode(const int categoryIndex, const int itemIndex)
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return NULL;
  else
    return _categories[categoryIndex].GetItemPrimitiveCode(itemIndex);
}
inline CifString *CifDataBlock::GetItemPrimitiveCode(const CifString category, const CifString item)
{
  int categoryIndex;
  categoryIndex = GetIndex(category);
  if (categoryIndex != -1)
    return _categories[categoryIndex].GetItemPrimitiveCode(item);
  else return NULL;
}
inline ReVarCifArray <CifCategoryIndex> *CifDataBlock::
  GetLinkParents(const int categoryIndex, const int itemIndex)
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  (ReVarCifArray <CifCategoryIndex> *) NULL;
  else return _categories[categoryIndex].GetLinkParents(itemIndex);
}
inline ReVarCifArray <CifCategoryIndex> *CifDataBlock::
  GetLinkParents(const CifString categoryName, const CifString itemKeyword)
{
  int categoryIndex;
  categoryIndex = GetIndex(categoryName);
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  (ReVarCifArray <CifCategoryIndex> *) NULL;
  else return _categories[categoryIndex].GetLinkParents(itemKeyword);
}
inline ReVarCifArray <CifCategoryIndex> *CifDataBlock::
  GetLinkChildren(const int categoryIndex, const int itemIndex)
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  (ReVarCifArray <CifCategoryIndex> *) NULL;
  else return _categories[categoryIndex].GetLinkChildren(itemIndex);
}
inline ReVarCifArray <CifCategoryIndex> *CifDataBlock::
  GetLinkChildren(const CifString categoryName, const CifString itemKeyword)
{
  int categoryIndex;
  categoryIndex = GetIndex(categoryName);
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  (ReVarCifArray <CifCategoryIndex> *) NULL;
  else return _categories[categoryIndex].GetLinkChildren(itemKeyword);
}
inline ReVarCifArray <CifCategoryIndex> *CifDataBlock::
  GetDependentItems(const int categoryIndex, const int itemIndex)
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  (ReVarCifArray <CifCategoryIndex> *) NULL;
  else return _categories[categoryIndex].GetDependentItems(itemIndex);
}
inline ReVarCifArray <CifCategoryIndex> *CifDataBlock::
  GetDependentItems(const CifString categoryName, const CifString itemKeyword)
{
  int categoryIndex;
  categoryIndex = GetIndex(categoryName);
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  (ReVarCifArray <CifCategoryIndex> *) NULL;
  else return _categories[categoryIndex].GetDependentItems(itemKeyword);
}
inline ReVarCifArray <CifRelatedItem> *CifDataBlock::
  GetRelatedItems(const int categoryIndex, const int itemIndex)
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  (ReVarCifArray <CifRelatedItem> *) NULL;
  else return _categories[categoryIndex].GetRelatedItems(itemIndex);
}
inline ReVarCifArray <CifRelatedItem> *CifDataBlock::
  GetRelatedItems(const CifString categoryName, const CifString itemKeyword)
{
  int categoryIndex;
  categoryIndex = GetIndex(categoryName);
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return  (ReVarCifArray <CifRelatedItem> *) NULL;
  else return _categories[categoryIndex].GetRelatedItems(itemKeyword);
}
inline int CifDataBlock::CountItem(const int categoryIndex)
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return 0;
  else return _categories[categoryIndex].CountItem();
}
inline int CifDataBlock::CountItem(const CifString categoryName)
{
  int categoryIndex;
  categoryIndex = GetIndex(categoryName);
  if (categoryIndex == -1)
    return CIF_CATEGORY_NOT_EXIST ;
  else return _categories[categoryIndex].CountItem();
}

/*
inline CifString *CifDataBlock::GetAliasName(const int index)
{
  if (index < 0 || index >= aliases.Length())
    return  (CifString *) NULL;
  else return aliases[index].GetAliasName();
}
inline CifString *CifDataBlock::GetAliasItemKeyword( const int index)
{
  if (index < 0 || index >= aliases.Length())
    return (CifString *)  NULL;
  else return aliases[index].GetItemKeyword();
}
inline CifString *CifDataBlock::GetAliasCategoryName(const int index)
{
  if (index < 0 || index >= aliases.Length())
    return (CifString *)  NULL;
  else return aliases[index].GetCategoryName();
}
*/

inline CifCategoryIndex *CifDataBlock::GetTableIndex(const CifString category, 
						     const CifString item)
{
  return GetTableIndex(category.Text(), item.Text());
}

inline CifCategoryIndex *CifDataBlock::GetTableIndex(const CifString item)
{
  return GetTableIndex(item.Text());
}
inline int CifDataBlock::GetInsertIndex(const CifString item)
{
  return GetInsertIndex(item.Text());
}

inline int CifDataBlock::GetItemValue(CifItemValue **itemValue, const int categoryIndex, 
				   const int itemIndex, const int rowIndex)
// ----------------------------------------------------------------------
//   GetItemValue() Gets itemValue from itemValues array
// --------------------------------------------------------------------- 
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return CIF_CATEGORY_NOT_EXIST;
  else return _categories[categoryIndex].GetItemValue(itemValue, itemIndex, 
						      rowIndex);
}

inline int CifDataBlock::GetItemValue(CifString **itemValue, const int categoryIndex, 
				   const int itemIndex, const int rowIndex)
// ----------------------------------------------------------------------
//   GetItemValue() Gets itemValue from itemValues array
// --------------------------------------------------------------------- 
{
  if (categoryIndex < 0 || categoryIndex >= _categories.Length())
    return CIF_CATEGORY_NOT_EXIST;
  else return _categories[categoryIndex].GetItemValue(itemValue, itemIndex, 
						  rowIndex);
}

inline int CifDataBlock::GetItemValue(CifItemValue **itemValue, const CifString categoryName, 
				   const CifString itemKeyword, const int rowIndex)
// ----------------------------------------------------------------------
//   GetItemValue() Gets itemValue from itemValues array
// --------------------------------------------------------------------- 
{
  int categoryIndex;
  categoryIndex = GetIndex(categoryName);
  if (categoryIndex == -1)
    return CIF_CATEGORY_NOT_EXIST ;
  else return _categories[categoryIndex].GetItemValue(itemValue, itemKeyword, rowIndex);

}

inline int CifDataBlock::GetItemValue(CifString **itemValue, const CifString categoryName, 
				   const CifString itemKeyword, const int rowIndex)
// ----------------------------------------------------------------------
//   GetItemValue() Gets itemValue from itemValues array
// --------------------------------------------------------------------- 
{
  int categoryIndex;
  categoryIndex = GetIndex(categoryName);
  if (categoryIndex == -1)
    return CIF_CATEGORY_NOT_EXIST ;
  else return _categories[categoryIndex].GetItemValue(itemValue,
					  itemKeyword, rowIndex);
}

inline CifCategory *CifDataBlock::AddCategory(CifDataBlock *dic, 
							   const CifString categoryName)

// ----------------------------------------------------------------------
//   InsertItemValue() Gets itemValue from itemValues array
// --------------------------------------------------------------------- 
{
  return AddCategory(dic, categoryName.Text());
						 
}

inline CifDataItem *CifDataBlock::AddDataItem(CifDataBlock *dic,
						 const int categoryIndex, 
						 const CifString itemName)
// ----------------------------------------------------------------------
//   AddDataItem() Gets itemValue from itemValues array
// --------------------------------------------------------------------- 
{
  return AddDataItem(dic, categoryIndex, itemName.Text());
}

inline void CifDataBlock::ErrorMessage(const int errorMessage, 
					   const int lineNo, const CifString message)
{
  ErrorMessage(errorMessage, lineNo, message.Text());
}
inline  CifString *CifDataBlock::GetError(const int errorIndex)
{
  if (errorIndex < 0 || errorIndex >= _errors.Length())
    return (CifString *) NULL;
  else return &_errors[errorIndex];
}

inline CifString *CifDataBlock::GetWarning(const int warningIndex)
{
  if (warningIndex < 0 || warningIndex >= _warnings.Length())
    return (CifString *) NULL;
  else return &_warnings[warningIndex];
}
inline void CifDataBlock::FreeWarning(const int warningIndex)
{
  if (warningIndex < 0 || warningIndex >= _warnings.Length())
    return;
  else _warnings.DeleteAt(warningIndex, 1);
}
inline void CifDataBlock::FreeError(const int errorIndex)
{
  if (errorIndex < 0 || errorIndex >= _errors.Length())
    return;
  else _errors.DeleteAt(errorIndex, 1);
}
#endif
 
