/*
FILE:     CifBuildReorganizer.C
*/
/*
VERSION:  4.101
*/
/*
DATE:     8/16/2004
*/
/*
  Comments and Questions to: sw-help@rcsb.rutgers.edu
*/
/*
COPYRIGHT 1999-2004 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. 
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "CifBuildReorganizer.h"

extern FileNavigator * fnav;
extern Word binSearch(const void *key, const void * base, size_t nel,
         size_t size, int (*compar)(const void *, const void *));

int sCompare(const void * a, const void * b) {
/*
-------------------------------------------------------------------------------
   sCompare(): (string compare) is a function used by binSearch() to search an
   array of char *.
-------------------------------------------------------------------------------
*/
  return strcmp(((char *) a), ((char *) b)); 
  //  return strcasecmp(((char *) a), ((char *) b)); 
}

CategoryBuildObj::CategoryBuildObj() {
/*
-------------------------------------------------------------------------------
  constructor that initializes the object
-------------------------------------------------------------------------------
*/
  Clear();
}

CategoryBuildObj::CategoryBuildObj(const char * dataBlockName, const char * categoryId) {
/*
-------------------------------------------------------------------------------
  constructor that initializes the object and sets the keys
-------------------------------------------------------------------------------
*/
  Clear();
  SetId(dataBlockName, categoryId);
}  

void CategoryBuildObj::SetId(const char *dataBlockName, const char *categoryId)
{/*
-------------------------------------------------------------------------------
  SetId() sets the keys of the object
-------------------------------------------------------------------------------
*/


  _id = (char *) malloc((strlen(categoryId) + 1)*sizeof(char));
  strcpy(_id, categoryId);  
  _datablock = (char *) malloc((strlen(dataBlockName) + 1)*sizeof(char));
  strcpy(_datablock, dataBlockName);
}

int CategoryBuildObj::GetObject(uWord which) {
/*
-------------------------------------------------------------------------------
  GetObject() calls all of the private Get methods so that the entire object
  can be retrieved from memory. The object# must be specified.
-------------------------------------------------------------------------------
*/
  uWord num;
  int err;
  err = 0;
  num = 0;
  if (_index) free(_index);
  _index = fnav->GetWords(which, num, err); 
  GetDescription();
  GetMandatoryCode();
  GetKeyItems();
  GetExamplesCase();
  GetExamplesDetail();
  GetCategoryGroups();
  GetCategoryMethods();
  GetDescriptionNDB();
  GetExamplesCaseNDB();
  GetExamplesDetailNDB();

  if (err == NO_ERROR) 
    return NO_ERROR; 
  else return err;
}

/*
  The following Get methods will retrieve the data members from persistent
  storage by calling on the FileNavigator class.
*/

int CategoryBuildObj::GetDescription() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_description) free(_description);
  if (_index[0] == 0) _description = NULL;
  else _description = fnav->GetString(_index[0], err);
  return err; 
}

int CategoryBuildObj::GetDescriptionNDB() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_descriptionNDB) free(_descriptionNDB);
  if (_index[7] == 0) _descriptionNDB = NULL;
  else _descriptionNDB = fnav->GetString(_index[7], err);
  return err; 
}

int CategoryBuildObj::GetMandatoryCode() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_mandatoryCode) free(_mandatoryCode);
  if (_index[1] == 0) _mandatoryCode = NULL;
  else _mandatoryCode = fnav->GetString(_index[1], err);
  return err; 
}

int CategoryBuildObj::GetKeyItems() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_keyItems) {
    for (uWord i = 0; i < _keyItemsNum; i++) 
      free(_keyItems[i]);
    free(_keyItems);
  }
  if (_index[2] == 0) _keyItems = NULL;
  else _keyItems = fnav->GetStrings(_index[2], _keyItemsNum, err);
  return err; 
}

int CategoryBuildObj::GetExamplesCase() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_examplesCase) {
    for (uWord i = 0; i < _examplesNum; i++) 
      free(_examplesCase[i]);
    free(_examplesCase);
  }
  if (_index[3] == 0) _examplesCase = NULL;
  else _examplesCase = fnav->GetStrings(_index[3], _examplesNum, err);
  return err; 
}

int CategoryBuildObj::GetExamplesDetail() {
  int err;
  err = 0;
  uWord num;
  num = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_examplesDetail) {
    for (uWord i = 0; i < _examplesNum; i++) 
      free(_examplesDetail[i]);
    free(_examplesDetail);
  }
  if (_index[4] == 0) _examplesDetail = NULL;
  else _examplesDetail = fnav->GetStrings(_index[4], num, err);
  return err; 
}

int CategoryBuildObj::GetExamplesCaseNDB() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_examplesCaseNDB) {
    for (uWord i = 0; i < _examplesNumNDB; i++) 
      free(_examplesCaseNDB[i]);
    free(_examplesCaseNDB);
  }
  if (_index[8] == 0) _examplesCaseNDB = NULL;
  else _examplesCaseNDB = fnav->GetStrings(_index[8], _examplesNumNDB, err);
  return err; 
}

int CategoryBuildObj::GetExamplesDetailNDB() {
  int err;
  err = 0;
  uWord num;
  num = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_examplesDetailNDB) {
    for (uWord i = 0; i < _examplesNumNDB; i++) 
      free(_examplesDetailNDB[i]);
    free(_examplesDetailNDB);
  }
  if (_index[9] == 0) _examplesDetailNDB = NULL;
  else _examplesDetailNDB = fnav->GetStrings(_index[9], num, err);
  return err; 
}

int CategoryBuildObj::GetCategoryGroups() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_categoryGroups) {
    for (uWord i = 0; i < _categoryGroupsNum; i++) 
      free(_categoryGroups[i]);
    free(_categoryGroups);
  }
  if (_index[5] == 0) _categoryGroups = NULL;
  else _categoryGroups = fnav->GetStrings(_index[5], _categoryGroupsNum, err);
  return err; 
}

int CategoryBuildObj::GetCategoryMethods() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_categoryMethods) {
    for (uWord i = 0; i < _categoryMethodsNum; i++) 
      free(_categoryMethods[i]);
    free(_categoryMethods);
  }
  if (_index[6] == 0) _categoryMethods = NULL;
  else _categoryMethods = fnav->GetStrings(_index[6], _categoryMethodsNum, err);
  return err; 
}


  
ItemBuildObj::ItemBuildObj() {
/*
-------------------------------------------------------------------------------
  constructor that initializes the object
-------------------------------------------------------------------------------
*/
  Clear();
}

ItemBuildObj::ItemBuildObj(const char * dataBlockName, const char * itemName) {
/*
-------------------------------------------------------------------------------
  constructor that initializes the object and sets the keys
-------------------------------------------------------------------------------
*/
  Clear();
  SetName(dataBlockName, itemName);
}

void ItemBuildObj::SetName(const char * dataBlockName, const char * itemName) {
/*
-------------------------------------------------------------------------------
  SetName() will set the keys of the object
-------------------------------------------------------------------------------
*/
  _name = (char *) malloc((strlen(itemName) + 1) * sizeof(char));
  strcpy(_name, itemName);
  _datablock = (char *) malloc((strlen(dataBlockName) + 1) * sizeof(char));
  strcpy(_datablock, dataBlockName);
}

int ItemBuildObj::GetObject(uWord which) {
/*
-------------------------------------------------------------------------------
  GetObject() will call all of the private Get methods so that the entire
  object can be retrieved from persistent storage.
-------------------------------------------------------------------------------
*/
  uWord num;
  int err;
  err = 0;
  num = 0;
  if (_index) free(_index);
  _index = fnav->GetWords(which, num, err); 
  GetDescription();
  GetType();
  GetPrimitiveCode();
  GetRegex();
  GetExamplesCase();
  GetExamplesDetail();
  GetEnumeration();
  GetEnumerationDetail();
  GetMandatoryCode();
  GetDefaultValue();
  GetUnits();
  GetRangeMin();
  GetRangeMax();
  GetAliases();
  GetAliasesDictionary();
  GetAliasesDictionaryVersion();
  GetItemStructure();
  GetItemStructureOrganization();
  GetDependents();
  GetRelated();
  GetRelatedFunctionCode();
  GetSubcategories();
  GetLinkedChildren();
  GetLinkedParents();
  GetMethods();
  GetTypeConditions();
  GetDescriptionNDB();
  GetExamplesCaseNDB();
  GetExamplesDetailNDB();
  GetEnumerationNDB();
  GetEnumerationDetailNDB();

  if (err == NO_ERROR) 
    return NO_ERROR; 
  else return err;
}

/*
  The following Get methods will retrieve the data members from persistent
  storage by calling on the FileNavigator class.
*/

int ItemBuildObj::GetDescription() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_description) free(_description);
  if (_index[0] == 0) _description = NULL;
  else _description = fnav->GetString(_index[0], err);
  return err; 
}

int ItemBuildObj::GetDescriptionNDB() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_descriptionNDB) free(_descriptionNDB);
  if (_index[26] == 0) _descriptionNDB = NULL;
  else _descriptionNDB = fnav->GetString(_index[26], err);
  return err; 
}

int ItemBuildObj::GetType() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_type) free(_type);
  if (_index[1] == 0) _type = NULL;
  else _type = fnav->GetString(_index[1], err);
  return err; 
}

int ItemBuildObj::GetPrimitiveCode() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_primitiveCode) free(_primitiveCode);
  if (_index[2] == 0) _type = NULL;
  else _primitiveCode = fnav->GetString(_index[2], err);
  return err; 
}

int ItemBuildObj::GetRegex() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_regex) free(_regex);
  if (_index[3] == 0) _regex = NULL;
  else _regex = fnav->GetString(_index[3], err);
  return err; 
}

int ItemBuildObj::GetExamplesCase()
{
  int err;
  err = 0;
  uWord i;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_examplesCase) {
    for (i = 0; i < _examplesNum; i++)
      free(_examplesCase[i]);
    free(_examplesCase);
  }
  if (_examplesDetail) {
    for (i = 0; i < _examplesNum; i++)
      free(_examplesDetail[i]);
    free(_examplesDetail);
  }
  if (_index[4] == 0) _examplesCase = NULL;
  else _examplesCase = fnav->GetStrings(_index[4], _examplesNum, err);
  return err;
}

int ItemBuildObj::GetExamplesDetail() {
  int err;
  err = 0;
  uWord exNum;
  exNum = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_index[5] == 0) _examplesDetail = NULL;
  else _examplesDetail = fnav->GetStrings(_index[5], exNum, err);
  if (exNum != _examplesNum) return -2;
  else return err;
}

int ItemBuildObj::GetEnumeration() {
  int err;
  err = 0;
  uWord i;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_enumeration) {
    for (i = 0; i < _enumerationNum; i++)
      free(_enumeration[i]);
    free(_enumeration);
  }
  if (_index[6] == 0) _enumeration = NULL;
  else _enumeration = fnav->GetStrings(_index[6], _enumerationNum, err);
  return err;
}

int ItemBuildObj::GetEnumerationDetail() {
  int err;
  err = 0;
  uWord i;
  uWord enNum;
  enNum = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_enumerationDetail) {
    for (i = 0; i < _enumerationNum; i++)
      free(_enumerationDetail[i]);
    free(_enumerationDetail);
  }
  if (_index[7] == 0) _enumerationDetail = NULL;
  else _enumerationDetail = fnav->GetStrings(_index[7], enNum, err);
  if (enNum != _enumerationNum) return -2;
  return err;
}


int ItemBuildObj::GetExamplesCaseNDB()
{
  int err;
  err = 0;
  uWord i;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_examplesCaseNDB) {
    for (i = 0; i < _examplesNumNDB; i++)
      free(_examplesCaseNDB[i]);
    free(_examplesCaseNDB);
  }
  if (_examplesDetailNDB) {
    for (i = 0; i < _examplesNumNDB; i++)
      free(_examplesDetailNDB[i]);
    free(_examplesDetailNDB);
  }
  if (_index[27] == 0) _examplesCaseNDB = NULL;
  else _examplesCaseNDB = fnav->GetStrings(_index[27], _examplesNumNDB, err);
  return err;
}

int ItemBuildObj::GetExamplesDetailNDB() {
  int err;
  err = 0;
  uWord exNum;
  exNum = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_index[28] == 0) _examplesDetailNDB = NULL;
  else _examplesDetailNDB = fnav->GetStrings(_index[28], exNum, err);
  if (exNum != _examplesNumNDB) return -2;
  else return err;
}

int ItemBuildObj::GetEnumerationNDB() {
  int err;
  err = 0;
  uWord i;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_enumerationNDB) {
    for (i = 0; i < _enumerationNumNDB; i++)
      free(_enumerationNDB[i]);
    free(_enumerationNDB);
  }
  if (_index[29] == 0) _enumerationNDB = NULL;
  else _enumerationNDB = fnav->GetStrings(_index[29], _enumerationNumNDB, err);
  return err;
}

int ItemBuildObj::GetEnumerationDetailNDB() {
  int err;
  err = 0;
  uWord i;
  uWord enNum;
  enNum = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_enumerationDetailNDB) {
    for (i = 0; i < _enumerationNumNDB; i++)
      free(_enumerationDetailNDB[i]);
    free(_enumerationDetailNDB);
  }
  if (_index[30] == 0) _enumerationDetailNDB = NULL;
  else _enumerationDetailNDB = fnav->GetStrings(_index[30], enNum, err);
  if (enNum != _enumerationNumNDB) return -2;
  return err;
}


int ItemBuildObj::GetMandatoryCode() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_mandatoryCode) free(_mandatoryCode);
  if (_index[8] == 0) _mandatoryCode = NULL;
  else _mandatoryCode = fnav->GetString(_index[8], err);
  return err; 
}


int ItemBuildObj::GetDefaultValue() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_defaultValue) free(_defaultValue);
  if (_index[9] == 0) _defaultValue = NULL;
  else _defaultValue = fnav->GetString(_index[9], err);
  return err; 
}

int ItemBuildObj::GetUnits() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_units) free(_units);
  if (_index[10] == 0) _units = NULL;
  else _units = fnav->GetString(_index[10], err);
  return err; 
}

int ItemBuildObj::GetRangeMin() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_rangeMin) {
    for (uWord i = 0; i < _rangeNum; i++) 
      free(_rangeMin[i]);
    free(_rangeMin);
  }
  if (_index[11] == 0) _rangeMin = NULL;
  else _rangeMin = fnav->GetStrings(_index[11], _rangeNum, err);
  return err; 
}

int ItemBuildObj::GetRangeMax() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_rangeMax) {
    for (uWord i = 0; i < _rangeNum; i++) 
      free(_rangeMax[i]);
    free(_rangeMax);
  }
  if (_index[12] == 0) _rangeMax = NULL;
  else _rangeMax = fnav->GetStrings(_index[12], _rangeNum, err);
  return err; 
}

int ItemBuildObj::GetAliases() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_aliases) {
    for (uWord i = 0; i < _aliasesNum; i++) 
      free(_aliases[i]);
    free(_aliases);
  }
  if (_index[13] == 0) _aliases = NULL;
  else _aliases = fnav->GetStrings(_index[13], _aliasesNum, err);
  return err; 
}

int ItemBuildObj::GetAliasesDictionary() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_aliasesDictionary) {
    for (uWord i = 0; i < _aliasesNum; i++) 
      free(_aliasesDictionary[i]);
    free(_aliasesDictionary);
  }
  if (_index[14] == 0) _aliasesDictionary = NULL;
  else _aliasesDictionary = fnav->GetStrings(_index[14], _aliasesNum, err);
  return err; 
}

int ItemBuildObj::GetAliasesDictionaryVersion() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_aliasesDictionaryVersion) {
    for (uWord i = 0; i < _aliasesNum; i++) 
      free(_aliasesDictionaryVersion[i]);
    free(_aliasesDictionaryVersion);
  }
  if (_index[15] == 0) _aliasesDictionaryVersion = NULL;
  else _aliasesDictionaryVersion = fnav->GetStrings(_index[15], _aliasesNum, err);
  return err; 
}

int ItemBuildObj::GetItemStructure() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemStructure) free(_itemStructure);
  if (_index[16] == 0) _itemStructure = NULL;
  else _itemStructure = fnav->GetString(_index[16], err);
  return err; 
}

int ItemBuildObj::GetItemStructureOrganization() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemStructureOrganization) free(_itemStructureOrganization);
  if (_index[17] == 0) _itemStructureOrganization = NULL;
  else _itemStructureOrganization = fnav->GetString(_index[17], err);
  return err; 
}

int ItemBuildObj::GetDependents() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_dependents) {
    for (uWord i = 0; i < _dependentsNum; i++) 
      free(_dependents[i]);
    free(_dependents);
  }
  if (_index[18] == 0) _dependents = NULL;
  else _dependents = fnav->GetStrings(_index[18], _dependentsNum, err);
  return err; 
}

int ItemBuildObj::GetRelated() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_related) {
    for (uWord i = 0; i < _relatedNum; i++) 
      free(_related[i]);
    free(_related);
  }
  if (_index[19] == 0) _related = NULL;
  else _related = fnav->GetStrings(_index[19], _relatedNum, err);
  return err; 
}

int ItemBuildObj::GetRelatedFunctionCode() {
  int err;
  err = 0;
  uWord n;
  n = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_relatedFunctionCode) {
    for (uWord i = 0; i < _relatedNum; i++) 
      free(_relatedFunctionCode[i]);
    free(_relatedFunctionCode);
  }
  if (_index[20] == 0) _relatedFunctionCode = NULL;
  else _relatedFunctionCode = fnav->GetStrings(_index[20], n, err);
  return err; 
}

int ItemBuildObj::GetSubcategories() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_subcategories) {
    for (uWord i = 0; i < _subcategoriesNum; i++) 
      free(_subcategories[i]);
    free(_subcategories);
  }
  if (_index[21] == 0) _subcategories = NULL;
  else _subcategories = fnav->GetStrings(_index[21], _subcategoriesNum, err);
  return err; 
}

int ItemBuildObj::GetLinkedChildren() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_linkedChildren) {
    for (uWord i = 0; i < _linkedChildrenNum; i++) 
      free(_linkedChildren[i]);
    free(_linkedChildren);
  }
  if (_index[22] == 0) _linkedChildren = NULL;
  else _linkedChildren = fnav->GetStrings(_index[22], _linkedChildrenNum, err);
  return err; 
}

int ItemBuildObj::GetLinkedParents() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_linkedParents) {
    for (uWord i = 0; i < _linkedParentsNum; i++) 
      free(_linkedParents[i]);
    free(_linkedParents);
  }
  if (_index[23] == 0) _linkedParents = NULL;
  else _linkedParents = fnav->GetStrings(_index[23], _linkedParentsNum, err);
  return err; 
}

int ItemBuildObj::GetMethods() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_methods) {
    for (uWord i = 0; i < _methodsNum; i++) 
      free(_methods[i]);
    free(_methods);
  }
  if (_index[24] == 0) _methods = NULL;
  else _methods = fnav->GetStrings(_index[24], _methodsNum, err);
  return err; 
}

int ItemBuildObj::GetTypeConditions() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_typeConditions) {
    for (uWord i = 0; i < _typeConditionsNum; i++) 
      free(_typeConditions[i]);
    free(_typeConditions);
  }
  if (_index[25] == 0) _typeConditions = NULL;
  else _typeConditions = fnav->GetStrings(_index[25], _typeConditionsNum, err);
  return err; 
}



SubcategoryBuildObj::SubcategoryBuildObj() {
/*
------------------------------------------------------------------------------
  constructor that initializes the object
------------------------------------------------------------------------------
*/
  Clear();
}

SubcategoryBuildObj::SubcategoryBuildObj(const char * dataBlockName, const char * subcategoryId) {
/*
------------------------------------------------------------------------------
  constructor that initializes the object and sets the keys
------------------------------------------------------------------------------
*/
  Clear();
  SetId(dataBlockName, subcategoryId);
}  

void SubcategoryBuildObj::SetId(const char * dataBlockName, const char *subcategoryId)
/*
------------------------------------------------------------------------------
  SetId() sets the keys of the object
------------------------------------------------------------------------------
*/
{
  _id = (char *) malloc((strlen(subcategoryId) + 1)*sizeof(char));
  strcpy(_id, subcategoryId);  
  _datablock = (char *) malloc((strlen(dataBlockName) + 1)*sizeof(char));
  strcpy(_datablock, dataBlockName);
}

int SubcategoryBuildObj::GetObject(uWord which) {
/*
-------------------------------------------------------------------------------
  GetObject() will call all of the private Get methods so that the entire
  object can be retrieved from persistent storage.
-------------------------------------------------------------------------------
*/
  uWord num;
  int err;
  err = 0;
  num = 0;
  if (_index) free(_index);
  _index = fnav->GetWords(which, num, err); 
  GetDescription();
  GetExamplesCase();
  GetExamplesDetail();
  GetMethods();

  if (err == NO_ERROR) 
    return NO_ERROR; 
  else return err;
}

/*
  The following Get methods will retrieve the data members from persistent
  storage by calling on the FileNavigator class.
*/

int SubcategoryBuildObj::GetDescription() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_description) free(_description);
  if (_index[0] == 0) _description = NULL;
  else _description = fnav->GetString(_index[0], err);
  return err; 
}

int SubcategoryBuildObj::GetExamplesCase() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_examplesCase) {
    for (uWord i = 0; i < _examplesNum; i++) 
      free(_examplesCase[i]);
    free(_examplesCase);
  }
  if (_index[1] == 0) _examplesCase = NULL;
  else _examplesCase = fnav->GetStrings(_index[1], _examplesNum, err);
  return err; 
}

int SubcategoryBuildObj::GetExamplesDetail() {
  int err;
  err = 0;
  uWord num;
  num = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_examplesDetail) {
    for (uWord i = 0; i < _examplesNum; i++) 
      free(_examplesDetail[i]);
    free(_examplesDetail);
  }
  if (_index[2] == 0) _examplesDetail = NULL;
  else _examplesDetail = fnav->GetStrings(_index[2], num, err);
  return err; 
}

int SubcategoryBuildObj::GetMethods() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_methods) {
    for (uWord i = 0; i < _methodsNum; i++) 
      free(_methods[i]);
    free(_methods);
  }
  if (_index[3] == 0) _methods = NULL;
  else _methods = fnav->GetStrings(_index[3], _methodsNum, err);
  return err; 
}



DictionaryBuildObj::DictionaryBuildObj() {
/*
------------------------------------------------------------------------------
  constructor that initializes the object
------------------------------------------------------------------------------
*/
  Clear();
}

DictionaryBuildObj::DictionaryBuildObj(const char * dName) {
/*
------------------------------------------------------------------------------
  constructor that initializes th object and sets the key
------------------------------------------------------------------------------
*/
  Clear();
  SetName(dName);
}  

void DictionaryBuildObj::SetName(const char * dname) {
/*
------------------------------------------------------------------------------
  SetName() sets the key of the object
------------------------------------------------------------------------------
*/
  _name = (char *) malloc((strlen(dname) + 1)*sizeof(char));
  strcpy(_name, dname);
}

int DictionaryBuildObj::GetObject(uWord which) {
/*
-------------------------------------------------------------------------------
  GetObject() will call all of the private Get methods so that the entire
  object can be retrieved from persistent storage.
-------------------------------------------------------------------------------
*/
  uWord num;
  num = 0;
  int err;
  err = 0;
  if (_index) free(_index);
  _index = fnav->GetWords(which, num, err); 
  GetTitle();
  GetVersion();
  GetHistoryVersion();
  GetHistoryUpdate();
  GetHistoryRevision();
  GetCategories();
  GetSubcategories();
  GetItems();
  GetMethods();
  GetMethodsId();
  GetMethodsList();
  GetMethodsListDetail();
  GetMethodsListInline();
  GetMethodsListCode();
  GetMethodsListLanguage();
  GetCategoryGroupList();
  GetCategoryGroupListParents();
  GetCategoryGroupListDescription();
  GetItemStructureListCode();
  GetItemStructureListIndex();
  GetItemStructureListDimension();
  GetItemTypeListCode();
  GetItemTypeListPrimitiveCode();
  GetItemTypeListConstruct();
  GetItemTypeListDetail();
  GetItemUnitsListCode();
  GetItemUnitsListDetail();
  GetItemUnitsConversionOperator();
  GetItemUnitsConversionFactor();
  GetItemUnitsConversionFromCode();
  GetItemUnitsConversionToCode();

  BuildItemList();
  BuildSubcategoryList();
  BuildCategoryList();

  if (err == NO_ERROR) 
    return NO_ERROR; 
  else return err;
}

/*
  The following Get methods will retrieve the data members from persistent
  storage by calling on the FileNavigator class.
*/

int DictionaryBuildObj::GetTitle() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_title) free(_title);
  if (_index[0] == 0) _title = NULL;
  else _title = fnav->GetString(_index[0], err);
  return err; 
}

int DictionaryBuildObj::GetVersion() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_version) free(_version);
  if (_index[1] == 0) _version = NULL;
  else _version = fnav->GetString(_index[1], err);
  return err; 
}

int DictionaryBuildObj::GetDescription() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_description) free(_description);
  if (_index[2] == 0) _description = NULL;
  else _description = fnav->GetString(_index[2], err);
  return err; 
}

int DictionaryBuildObj::GetHistoryVersion() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_historyVersion) {
    for (uWord i = 0; i < _historyNum; i++) 
      free(_historyVersion[i]);
    free(_historyVersion);
  }
  if (_index[3] == 0) _historyVersion = NULL;
  else _historyVersion = fnav->GetStrings(_index[3], _historyNum, err);
  return err; 
}

int DictionaryBuildObj::GetHistoryUpdate() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_historyUpdate) {
    for (uWord i = 0; i < _historyNum; i++) 
      free(_historyUpdate[i]);
    free(_historyUpdate);
  }
  if (_index[4] == 0) _historyUpdate = NULL;
  else _historyUpdate = fnav->GetStrings(_index[4], _historyNum, err);
  return err; 
}

int DictionaryBuildObj::GetHistoryRevision() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_historyRevision) {
    for (uWord i = 0; i < _historyNum; i++) 
      free(_historyRevision[i]);
    free(_historyRevision);
  }
  if (_index[5] == 0) _historyRevision = NULL;
  else _historyRevision = fnav->GetStrings(_index[5], _historyNum, err);
  return err; 
}

int DictionaryBuildObj::GetCategories() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_categories) {
    for (uWord i = 0; i < _categoriesNum; i++) 
      free(_categories[i]);
    free(_categories);
  }
  if (_index[6] == 0) _categories = NULL;
  else _categories = fnav->GetStrings(_index[6], _categoriesNum, err);
  return err; 
}

int DictionaryBuildObj::GetSubcategories() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_subcategories) {
    for (uWord i = 0; i < _subcategoriesNum; i++) 
      free(_subcategories[i]);
    free(_subcategories);
  }
  if (_index[7] == 0) _subcategories = NULL;
  else _subcategories = fnav->GetStrings(_index[7], _subcategoriesNum, err);
  return err; 
}

int DictionaryBuildObj::GetItems() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_items) {
    for (uWord i = 0; i < _itemsNum; i++) 
      free(_items[i]);
    free(_items);
  }
  if (_index[8] == 0) _items = NULL;
  else _items = fnav->GetStrings(_index[8], _itemsNum, err);
  return err; 
}

int DictionaryBuildObj::GetMethods() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_methods) {
    for (uWord i = 0; i < _methodsNum; i++) 
      free(_methods[i]);
    free(_methods);
  }
  if (_index[9] == 0) _methods = NULL;
  else _methods = fnav->GetStrings(_index[9], _methodsNum, err);
  return err; 
}

int DictionaryBuildObj::GetMethodsId() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_methodsId) {
    for (uWord i = 0; i < _methodsNum; i++) 
      free(_methodsId[i]);
    free(_methodsId);
  }
  if (_index[10] == 0) _methodsId = NULL;
  else _methodsId = fnav->GetStrings(_index[10], _methodsNum, err);
  return err; 
}

int DictionaryBuildObj::GetMethodsList() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_methodsList) {
    for (uWord i = 0; i < _methodsListNum; i++) 
      free(_methodsList[i]);
    free(_methodsList);
  }
  if (_index[11] == 0) _methodsList = NULL;
  else _methodsList = fnav->GetStrings(_index[11], _methodsListNum, err);
  return err; 
}

int DictionaryBuildObj::GetMethodsListDetail() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_methodsListDetail) {
    for (uWord i = 0; i < _methodsListNum; i++) 
      free(_methodsListDetail[i]);
    free(_methodsListDetail);
  }
  if (_index[12] == 0) _methodsListDetail = NULL;
  else _methodsListDetail = fnav->GetStrings(_index[12], _methodsListNum, err);
  return err; 
}

int DictionaryBuildObj::GetMethodsListInline() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_methodsListInline) {
    for (uWord i = 0; i < _methodsListNum; i++) 
      free(_methodsListInline[i]);
    free(_methodsListInline);
  }
  if (_index[13] == 0) _methodsListInline = NULL;
  else _methodsListInline = fnav->GetStrings(_index[13], _methodsListNum, err);
  return err; 
}

int DictionaryBuildObj::GetMethodsListCode() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_methodsListCode) {
    for (uWord i = 0; i < _methodsListNum; i++) 
      free(_methodsListCode[i]);
    free(_methodsListCode);
  }
  if (_index[14] == 0) _methodsListCode = NULL;
  else _methodsListCode = fnav->GetStrings(_index[14], _methodsListNum, err);
  return err; 
}

int DictionaryBuildObj::GetMethodsListLanguage() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_methodsListLanguage) {
    for (uWord i = 0; i < _methodsListNum; i++) 
      free(_methodsListLanguage[i]);
    free(_methodsListLanguage);
  }
  if (_index[15] == 0) _methodsListLanguage = NULL;
  else _methodsListLanguage = fnav->GetStrings(_index[15], _methodsListNum, err);
  return err; 
}

int DictionaryBuildObj::GetCategoryGroupList() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_categoryGroupList) {
    for (uWord i = 0; i < _categoryGroupListNum; i++) 
      free(_categoryGroupList[i]);
    free(_categoryGroupList);
  }
  if (_index[16] == 0) _categoryGroupList = NULL;
  else _categoryGroupList = fnav->GetStrings(_index[16], _categoryGroupListNum, err);
  return err; 
}

int DictionaryBuildObj::GetCategoryGroupListParents() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_categoryGroupListParents) {
    for (uWord i = 0; i < _categoryGroupListNum; i++) 
      free(_categoryGroupListParents[i]);
    free(_categoryGroupListParents);
  }
  if (_index[17] == 0) _categoryGroupListParents = NULL;
  else _categoryGroupListParents = fnav->GetStrings(_index[17], _categoryGroupListNum, err);
  return err; 
}

int DictionaryBuildObj::GetCategoryGroupListDescription() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_categoryGroupListDescription) {
    for (uWord i = 0; i < _categoryGroupListNum; i++) 
      free(_categoryGroupListDescription[i]);
    free(_categoryGroupListDescription);
  }
  if (_index[18] == 0) _categoryGroupListDescription = NULL;
  else _categoryGroupListDescription = fnav->GetStrings(_index[18], _categoryGroupListNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemStructureListCode() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemStructureListCode) {
    for (uWord i = 0; i < _itemStructureListNum; i++) 
      free(_itemStructureListCode[i]);
    free(_itemStructureListCode);
  }
  if (_index[19] == 0) _itemStructureListCode = NULL;
  else _itemStructureListCode = fnav->GetStrings(_index[19], _itemStructureListNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemStructureListIndex() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemStructureListIndex) {
    for (uWord i = 0; i < _itemStructureListNum; i++) 
      free(_itemStructureListIndex[i]);
    free(_itemStructureListIndex);
  }
  if (_index[20] == 0) _itemStructureListIndex = NULL;
  else _itemStructureListIndex = fnav->GetStrings(_index[20], _itemStructureListNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemStructureListDimension() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemStructureListDimension) {
    for (uWord i = 0; i < _itemStructureListNum; i++) 
      free(_itemStructureListDimension[i]);
    free(_itemStructureListDimension);
  }
  if (_index[21] == 0) _itemStructureListDimension = NULL;
  else _itemStructureListDimension = fnav->GetStrings(_index[21], _itemStructureListNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemTypeListCode() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemTypeListCode) {
    for (uWord i = 0; i < _itemTypeListNum; i++) 
      free(_itemTypeListCode[i]);
    free(_itemTypeListCode);
  }
  if (_index[22] == 0) _itemTypeListCode = NULL;
  else _itemTypeListCode = fnav->GetStrings(_index[22], _itemTypeListNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemTypeListPrimitiveCode() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemTypeListPrimitiveCode) {
    for (uWord i = 0; i < _itemTypeListNum; i++) 
      free(_itemTypeListPrimitiveCode[i]);
    free(_itemTypeListPrimitiveCode);
  }
  if (_index[23] == 0) _itemTypeListPrimitiveCode = NULL;
  else _itemTypeListPrimitiveCode = fnav->GetStrings(_index[23], _itemTypeListNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemTypeListConstruct() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemTypeListConstruct) {
    for (uWord i = 0; i < _itemTypeListNum; i++) 
      free(_itemTypeListConstruct[i]);
    free(_itemTypeListConstruct);
  }
  if (_index[24] == 0) _itemTypeListConstruct = NULL;
  else _itemTypeListConstruct = fnav->GetStrings(_index[24], _itemTypeListNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemTypeListDetail() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemTypeListDetail) {
    for (uWord i = 0; i < _itemTypeListNum; i++) 
      free(_itemTypeListDetail[i]);
    free(_itemTypeListDetail);
  }
  if (_index[25] == 0) _itemTypeListDetail = NULL;
  else _itemTypeListDetail = fnav->GetStrings(_index[25], _itemTypeListNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemUnitsListCode() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemUnitsListCode) {
    for (uWord i = 0; i < _itemUnitsListNum; i++) 
      free(_itemUnitsListCode[i]);
    free(_itemUnitsListCode);
  }
  if (_index[26] == 0) _itemUnitsListCode = NULL;
  else _itemUnitsListCode = fnav->GetStrings(_index[26], _itemUnitsListNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemUnitsListDetail() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemUnitsListDetail) {
    for (uWord i = 0; i < _itemUnitsListNum; i++) 
      free(_itemUnitsListDetail[i]);
    free(_itemUnitsListDetail);
  }
  if (_index[27] == 0) _itemUnitsListDetail = NULL;
  else _itemUnitsListDetail = fnav->GetStrings(_index[27], _itemUnitsListNum,err);
  return err; 
}

int DictionaryBuildObj::GetItemUnitsConversionOperator() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemUnitsConversionOperator) {
    for (uWord i = 0; i < _itemUnitsConversionNum; i++) 
      free(_itemUnitsConversionOperator[i]);
    free(_itemUnitsConversionOperator);
  }
  if (_index[28] == 0) _itemUnitsConversionOperator = NULL;
  else _itemUnitsConversionOperator = fnav->GetStrings(_index[28], _itemUnitsConversionNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemUnitsConversionFactor() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemUnitsConversionFactor) {
    for (uWord i = 0; i < _itemUnitsConversionNum; i++) 
      free(_itemUnitsConversionFactor[i]);
    free(_itemUnitsConversionFactor);
  }
  if (_index[29] == 0) _itemUnitsConversionFactor = NULL;
  else _itemUnitsConversionFactor = fnav->GetStrings(_index[29], _itemUnitsConversionNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemUnitsConversionFromCode() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemUnitsConversionFromCode) {
    for (uWord i = 0; i < _itemUnitsConversionNum; i++) 
      free(_itemUnitsConversionFromCode[i]);
    free(_itemUnitsConversionFromCode);
  }
  if (_index[30] == 0) _itemUnitsConversionFromCode = NULL;
  else _itemUnitsConversionFromCode = fnav->GetStrings(_index[30], _itemUnitsConversionNum, err);
  return err; 
}

int DictionaryBuildObj::GetItemUnitsConversionToCode() {
  int err;
  err = 0;
  if (!_index) return INDEX_NOT_CONSTRUCTED;
  if (_itemUnitsConversionToCode) {
    for (uWord i = 0; i < _itemUnitsConversionNum; i++) 
      free(_itemUnitsConversionToCode[i]);
    free(_itemUnitsConversionToCode);
  }
  if (_index[31] == 0) _itemUnitsConversionToCode = NULL;
  else _itemUnitsConversionToCode = fnav->GetStrings(_index[31], _itemUnitsConversionNum, err);
  return err; 
}

ItemBuildObj * DictionaryBuildObj::GetItem(const char * itemName) {
/*
------------------------------------------------------------------------------
  GetItem() searches through the object's list of items and returns the
  ItemBuildObject if it is in memory. Otherwise, it constructs the object,
  adds it to the list of in-memory objects, and returns the newly constructed
  object.
------------------------------------------------------------------------------
*/
  Word ind = binSearch(itemName, _itemsList.keys, _itemsList.numKeys, sizeof(char *), sCompare);
  if (ind < 0 || ind > (int) _itemsList.numKeys) return NULL;

  if (_itemsList.memIds[ind] != 0)
    return _itemObjs[_itemsList.memIds[ind]];
  _itemsList.memIds[ind] = _lastItemInMem;  
  _itemObjs[_lastItemInMem] = new ItemBuildObj;
  (_itemObjs[_lastItemInMem])->SetName(_name, itemName);
  (_itemObjs[_lastItemInMem])->GetObject(_itemsList.objectIds[ind]);

  return _itemObjs[_lastItemInMem++];   
}

CategoryBuildObj * DictionaryBuildObj::GetCategory(const char * categoryName){
/*
------------------------------------------------------------------------------
  GetCategory() searches through the object's list of categories and returns
  the CategoryBuildObj if it is in memory. Otherwise, it constructs the
  object, adds it to the list of in-memory objects, and returns the newly
  constructed object.
------------------------------------------------------------------------------
*/
  Word ind = binSearch(categoryName, _categoriesList.keys, _categoriesList.numKeys, sizeof(char *), sCompare);
  if (ind < 0 || ind > (int) _categoriesList.numKeys) return NULL;
  if (_categoriesList.memIds[ind] != 0)
    return _categoryObjs[_categoriesList.memIds[ind]];
  _categoriesList.memIds[ind] = _lastCategoryInMem;  
  _categoryObjs[_lastCategoryInMem] = new CategoryBuildObj;
  (_categoryObjs[_lastCategoryInMem])->SetId(_name, categoryName);
  (_categoryObjs[_lastCategoryInMem])->GetObject(_categoriesList.objectIds[ind]);

  return _categoryObjs[_lastCategoryInMem++];   
}

SubcategoryBuildObj * DictionaryBuildObj::GetSubcategory(const char * subcategoryName){
/*
------------------------------------------------------------------------------
  GetSub_category() searches through the object's list of subcategories and
  returns the SubcategoryBuildObj if it is in memory. Otherwise, it constructs
  the object, adds it to the list of in-memory objects, and returns the newly
  constructed object.
------------------------------------------------------------------------------
*/
  Word ind = binSearch(subcategoryName, _subcategoriesList.keys, _subcategoriesList.numKeys, sizeof(char *), sCompare);
  if (ind < 0 || ind > (int) _subcategoriesList.numKeys) return NULL;
  if (_subcategoriesList.memIds[ind] != 0)
    return _subcategoryObjs[_subcategoriesList.memIds[ind]];
  _subcategoriesList.memIds[ind] = _lastSubcategoryInMem;  
  _subcategoryObjs[_lastSubcategoryInMem] = new SubcategoryBuildObj;
  (_subcategoryObjs[_lastSubcategoryInMem])->SetId(_name, subcategoryName);
  (_subcategoryObjs[_lastSubcategoryInMem])->GetObject(_subcategoriesList.objectIds[ind]);

  return _subcategoryObjs[_lastSubcategoryInMem++];   
}

void DictionaryBuildObj::Reset() {
/*
-------------------------------------------------------------------------------
  Reset() frees all owned memory. Overr_ides DictionaryObjBase::Reset()
-------------------------------------------------------------------------------
*/
  Word i;
  DictionaryObjBase::Reset();
  if (_itemsList.objectIds) free(_itemsList.objectIds);
  if (_itemsList.memIds) free(_itemsList.memIds);
  if (_itemObjs) {
    for (i = 0; i < (int) _lastItemInMem; i++) {
      if (_itemObjs[i]) free(_itemObjs[i]);
    }
    free(_itemObjs);
  }
  if (_subcategoryObjs) {
    for (i = 0; i < (int) _lastSubcategoryInMem; i++) {
      if (_subcategoryObjs[i]) free(_subcategoryObjs[i]);
    }
    free(_subcategoryObjs);
  }    
  if (_categoryObjs) {
    for (i = 0; i < (int) _lastCategoryInMem; i++) {
      if (_categoryObjs[i]) free(_categoryObjs[i]);
    }
    free(_categoryObjs);
  }    

  Clear();
}

void DictionaryBuildObj::Clear() {
/*
-------------------------------------------------------------------------------
  Clear() initializes the object. Overr_ides DictionaryObjBase::Clear()
-------------------------------------------------------------------------------
*/
  DictionaryObjBase::Clear();
  _itemsList.numKeys = 0;
  _itemsList.keys = NULL;
  _itemsList.objectIds = NULL;
  _itemsList.memIds = NULL;
  _subcategoriesList.numKeys = 0;
  _subcategoriesList.keys = NULL;
  _subcategoriesList.objectIds = NULL;
  _subcategoriesList.memIds = NULL;
  _categoriesList.numKeys = 0;
  _categoriesList.keys = NULL;
  _categoriesList.objectIds = NULL;
  _categoriesList.memIds = NULL;
  _lastItemInMem = 1;
  _lastSubcategoryInMem = 1;
  _lastCategoryInMem = 1;
  _itemObjs = NULL;
  _subcategoryObjs = NULL;
  _categoryObjs = NULL;
}

int DictionaryBuildObj::BuildItemList() {
/*
-------------------------------------------------------------------------------
  BuildItemList() retrieves from disk the information needed to load in the
  itemObjs from disk into memory.
-------------------------------------------------------------------------------
*/
  int err;
  err = 0;
  if (_index[32] == 0) return BUILD_LIST_ERROR;
  _itemsList.objectIds = fnav->GetUWords(_index[32], _itemsList.numKeys, err);

  _itemsList.keys = _items;

  _itemsList.memIds = (uWord *) calloc(_itemsList.numKeys, WORDSIZE);
  _itemObjs = (ItemBuildObj **) calloc(_itemsList.numKeys + 1, sizeof(ItemBuildObj *));
  return NO_ERROR;
}

int DictionaryBuildObj::BuildSubcategoryList() {
/*
-------------------------------------------------------------------------------
  BuildSubcategoryList() retrieves from disk the information needed to load in
  the SubcategoryObjs from disk into memory.
-------------------------------------------------------------------------------
*/
  int err;
  err = 0;
  if (_index[33] == 0) return BUILD_LIST_ERROR;
  _subcategoriesList.objectIds = fnav->GetUWords(_index[33], _subcategoriesList.numKeys, err);

  _subcategoriesList.keys = _subcategories;

  _subcategoriesList.memIds = (uWord *) calloc(_subcategoriesList.numKeys, WORDSIZE);
  _subcategoryObjs = (SubcategoryBuildObj **) calloc(_subcategoriesList.numKeys + 1, sizeof(SubcategoryBuildObj *));
  return NO_ERROR;
}

int DictionaryBuildObj::BuildCategoryList() {
/*
-------------------------------------------------------------------------------
  BuildCategoryList() retrieves from disk the information needed to load in
  the CategoryObjs from disk into memory.
-------------------------------------------------------------------------------
*/
  int err;
  err = 0;
  if (_index[34] == 0) return BUILD_LIST_ERROR;
  _categoriesList.objectIds = fnav->GetUWords(_index[34], _categoriesList.numKeys, err);

  _categoriesList.keys = _categories;

  _categoriesList.memIds = (uWord *) calloc(_categoriesList.numKeys, WORDSIZE);
  _categoryObjs = (CategoryBuildObj **) calloc(_categoriesList.numKeys + 1, sizeof(CategoryBuildObj *));
  return NO_ERROR;
}

int DictionaryBuildObj::GetAllItems() {
/*
-------------------------------------------------------------------------------
  GetAllItems() is a method that gets all _items in this _datablock/dictionary
  and prints them out
-------------------------------------------------------------------------------
*/
  uWord i = 0;
  ItemBuildObj * ibo;
  for (i = 0; i < _itemsNum; i++) {
    ibo = GetItem(_items[i]);
    if (ibo) {
      ibo->PrintObject();
      ibo->Reset();
    }  else {
      printf("Failed to load item %s\n",_items[i]);
    }
  }
  return NO_ERROR;
}

int DictionaryBuildObj::GetAllSubcategories() {
/*
-------------------------------------------------------------------------------
  GetAllSubcategories() is a method that gets all _subcategories in this
  datablock/dictionary and prints them out
-------------------------------------------------------------------------------
*/
  uWord i = 0;
  SubcategoryBuildObj * sbo;
  for (i = 0; i < _subcategoriesNum; i++) {
    sbo = GetSubcategory(_subcategories[i]);
    if (sbo) {
      sbo->PrintObject();
      sbo->Reset();
    }  else {
      printf("Failed to load subcategory %s\n",_subcategories[i]);
    }
  }
  return NO_ERROR;
}

int DictionaryBuildObj::GetAllCategories() {
/*
-------------------------------------------------------------------------------
  GetAllCategories() is a method that gets all categories in this 
  datablock/dictionary and prints them out
-------------------------------------------------------------------------------
*/
  uWord i = 0;
  CategoryBuildObj * cbo;
  for (i = 0; i < _categoriesNum; i++) {
    cbo = GetCategory(_categories[i]);
    if (cbo) {
      cbo->PrintObject();
      cbo->Reset();
    } else {
      printf("Failed to load category %s\n",_categories[i]);
    }
  }
  return NO_ERROR;
}
