//
// File: hdbClass.cpp
//
// Legal Notice: This file is part of the HadronZoo C++ Class Library. Copyright 2025 HadronZoo Project (http://www.hadronzoo.com)
//
// The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free
// Software Foundation, either version 3 of the License, or any later version.
//
// The HadronZoo C++ Class Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses.
//
//
// Implimentation of the HadronZoo Proprietary Database Suite
//
#include <iostream>
#include <fstream>
#include <cstdio>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "hzBasedefs.h"
#include "hzString.h"
#include "hzChars.h"
#include "hzChain.h"
#include "hzDate.h"
#include "hzTextproc.h"
#include "hzCodec.h"
#include "hzDocument.h"
#include "hzDirectory.h"
#include "hzDatabase.h"
#include "hzDelta.h"
#include "hzProcess.h"
using namespace std ;
/*
** Variables
*/
// Group 1 Datatyeps: C++ Fundamental
global const hdbCpptype* datatype_DIGEST ; // MD5 hash value
global const hdbCpptype* datatype_DOUBLE ; // 64 bit floating point value
global const hdbCpptype* datatype_INT64 ; // 64-bit Signed integer
global const hdbCpptype* datatype_INT32 ; // 32-bit Signed integer
global const hdbCpptype* datatype_INT16 ; // 16-bit Signed integer
global const hdbCpptype* datatype_BYTE ; // 8-bit Signed integer
global const hdbCpptype* datatype_UINT64 ; // 64-bit Positive integer
global const hdbCpptype* datatype_UINT32 ; // 32-bit Positive integer
global const hdbCpptype* datatype_UINT16 ; // 16-bit Positive integer
global const hdbCpptype* datatype_UBYTE ; // 8-bit Positive integer
global const hdbCpptype* datatype_BOOL ; // either true or false
// Group 2 Datatypes: HadronZoo Defined types (fixed size)
global const hdbHzotype* datatype_DOMAIN ; // Internet Domain
global const hdbHzotype* datatype_EMADDR ; // Email Address
global const hdbHzotype* datatype_URL ; // Universal Resource Locator
global const hdbHzotype* datatype_PHONE ; // Phone number (limited aphabet, standard form, likely to be unique to data object)
global const hdbHzotype* datatype_IPADDR ; // IP Address
global const hdbHzotype* datatype_TIME ; // No of seconds since midnight (4 bytes)
global const hdbHzotype* datatype_SDATE ; // No of days since Jan 1st year 0000
global const hdbHzotype* datatype_XDATE ; // Full date & time
global const hdbHzotype* datatype_STRING ; // Any string, treated as a single value
global const hdbHzotype* datatype_TEXT ; // Any string, treated as a series of words, stored on disk, frequent change
global const hdbHzotype* datatype_BINARY ; // File assummed to be un-indexable (eg image). Stored on disk, infrequent change.
global const hdbHzotype* datatype_TXTDOC ; // Document from which text can be extracted/indexed. Stored on disk, infrequent change.
extern hzDeltaClient* _hzGlobal_DeltaClient ; // Total current delta clients
/*
** Init Sequence Functions
*/
const char* _hdb_showinitstate (hdbIniStat nState)
{
static const char* _istates[] =
{
"HDB_CLASS_INIT_NONE",
"HDB_CLASS_INIT_PROG",
"HDB_CLASS_INIT_DONE",
"HDB_REPOS_INIT_PROG",
"HDB_REPOS_INIT_DONE",
"HDB_REPOS_OPEN",
"HDB_REPOS_INIT_UNDEF",
""
} ;
if (nState == HDB_CLASS_INIT_NONE) return _istates[0] ;
if (nState == HDB_CLASS_INIT_PROG) return _istates[1] ;
if (nState == HDB_CLASS_INIT_DONE) return _istates[2] ;
if (nState == HDB_REPOS_INIT_PROG) return _istates[3] ;
if (nState == HDB_REPOS_INIT_DONE) return _istates[4] ;
if (nState == HDB_REPOS_OPEN) return _istates[5] ;
return _istates[6] ;
}
void _hdb_ck_initstate (const hzString& objName, hdbIniStat eActual, hdbIniStat eExpect)
{
// Exit on cases of wrong initialization
if (eActual == eExpect)
return ;
hzexit(E_INITFAIL, "Target DB entity [%s] Actual init state %s. Expected %s\n", *objName, _hdb_showinitstate(eActual), _hdb_showinitstate(eExpect)) ;
}
/*
** hdbEnum Functions
*/
hzEcode hdbEnum::AddItem (const hzString& strValue)
{
// Add a string value to the enumerated set of strings using the default value system.
uint32_t strNo ; // String number
if (!strValue)
return E_ARGUMENT ;
// strNo = _hzGlobal_ReposStrings->Locate(*strValue) ;
// if (!strNo)
// strNo = _hzGlobal_ReposStrings->Insert(strValue) ;
strNo = m_Numbers.Count() ;
m_Numbers.Add(strNo) ;
m_Strings.Add(strValue) ;
return E_OK ;
}
hzEcode hdbEnum::AddItem (const hzString& strValue, uint32_t numValue)
{
// Add a string value to the enumerated set of strings but with a specified value.
uint32_t strNo ; // String number
if (!strValue)
return E_ARGUMENT ;
// strNo = _hzGlobal_ReposStrings->Locate(*strValue) ;
// if (!strNo)
// strNo = _hzGlobal_ReposStrings->Insert(strValue) ;
strNo = m_Numbers.Count() ;
m_Numbers.Add(strNo) ;
m_Strings.Add(strValue) ;
return E_OK ;
}
/*
** hdbMember Functions
*/
hdbMember::hdbMember (void)
{
m_pClass = 0 ;
m_pType = 0 ;
m_pSpec = 0 ;
m_MemberUID = 0 ;
m_popCtl = HDB_MBR_POP_UNSPECIFIED ;
m_nPosn = 0 ;
m_nOsetStd = -1 ;
m_nOsetAux = -1 ;
m_sizeCore = 0 ;
m_sizeAux = 0 ;
m_sizeDatum = 0 ;
}
hzEcode hdbMember::Init (const hdbClass* pClass, const hdbDatatype* pType, const hzString& name, uint32_t nPosn, hdbPopCtl popCtl)
{
// Initialize the data object class member with name and data type
//
// Arguments: 1) pClass Data class this member belongs to
// 2) type HadronZoo data type
// 3) name Member name
// 4) minPop Minimum number of values the member may have in a real class instance (for repository inserts)
// 5) maxPop Maximum number of values
// 6) nPosn Member position
//
// Returns: E_ARGUMENT If the class, data type, or member name has not been supplied
// E_SETONCE If we are attempting to rename the member
// E_OK If operation was successful
_hzfunc("hdbClass::Member::Init") ;
const hdbEnum* pEnum ; // The actual defined enum (for multi-value enum members only)
hzEcode rc = E_OK ; // Return code
// No member name?
if (!pClass) return E_ARGUMENT ;
if (!pType) return E_ARGUMENT ;
if (!name) return E_ARGUMENT ;
// Member already Init?
if (m_Name)
return E_SETONCE ;
m_pClass = pClass ;
m_Name = name ;
m_pType = pType ;
m_popCtl = popCtl ;
m_nPosn = nPosn ;
// Set value size according to type and expected population
if (Singular())
{
switch (pType->Basetype())
{
case BASETYPE_DIGEST: m_sizeDatum = 16 ;
break ;
case BASETYPE_PHONE:
case BASETYPE_XDATE:
case BASETYPE_DOUBLE:
case BASETYPE_UINT64:
case BASETYPE_INT64: m_sizeDatum = 8 ;
break ;
case BASETYPE_BINARY:
case BASETYPE_TXTDOC: m_sizeCore = m_sizeDatum = 4 ;
m_sizeAux = 8 ;
break ;
case BASETYPE_UINT32:
case BASETYPE_INT32:
case BASETYPE_TIME:
case BASETYPE_SDATE:
case BASETYPE_STRING:
case BASETYPE_DOMAIN:
case BASETYPE_EMADDR:
case BASETYPE_URL:
case BASETYPE_IPADDR:
case BASETYPE_TEXT:
case BASETYPE_APPDEF: m_sizeDatum = 4 ;
break ;
case BASETYPE_UINT16:
case BASETYPE_INT16: if (Multiple())
rc = hzerr(E_TYPE, "UINT16/INT16 cannot be multiple value") ;
m_sizeDatum = 2 ;
break ;
case BASETYPE_ENUM: m_sizeDatum = m_sizeCore = 1 ;
break ;
case BASETYPE_BYTE:
case BASETYPE_UBYTE: m_sizeDatum = 1 ;
break ;
case BASETYPE_BOOL:
case BASETYPE_TBOOL: m_sizeDatum = 0 ;
if (Multiple())
rc = hzerr(E_TYPE, "BOOL/TBOOL cannot be multiple value") ;
break ;
default: rc = hzerr(E_TYPE, "Data type %s cannot be singular", Basetype2Txt(pType->Basetype())) ;
break ;
}
}
else
{
// Multiple - so less applicable data types
switch (pType->Basetype())
{
case BASETYPE_CLASS: m_sizeDatum = m_sizeCore = 8 ;
break ;
case BASETYPE_ENUM: pEnum = dynamic_cast<const hdbEnum*>(m_pType) ;
if (!pEnum)
return hzerr(E_TYPE, "ENUM type but no enum found") ;
m_sizeCore = (pEnum->Count()/8) ;
m_sizeCore += pEnum->Count()%8 ? 1 : 0 ;
m_sizeDatum = m_sizeCore ;
break ;
default: rc = hzerr(E_TYPE, "Data type %s cannot be multiple value", Basetype2Txt(pType->Basetype())) ;
break ;
}
}
if (rc != E_OK)
return rc ;
if (Singular())
m_sizeCore = m_sizeDatum ;
else
m_sizeCore = 8 ;
return E_OK ;
}
hzEcode hdbMember::SetSpec (const hdsFldspec* pSpec) const
{
// Set Field Specification for the member. Relevant only to webapp forms. Not relevant to HDB operation.
//
// Argument: pSpec The supplied Dissemino field spec
//
// Returns: E_ARGUMENT If no field spec is supplied
// E_DUPLICATE If the field spec has already been set
// E_OK Operation successful
if (!pSpec) return E_ARGUMENT ;
if (m_pSpec) return E_DUPLICATE ;
m_pSpec = pSpec ;
return E_OK ;
}
hzEcode hdbMember::_setId (uint32_t mbrId) const
{
// Set Field Specification for the member. Relevant only to webapp forms. Not relevant to HDB operation.
//
// Argument: pSpec The supplied Dissemino field spec
//
// Returns: E_ARGUMENT If no field spec is supplied
// E_DUPLICATE If the field spec has already been set
// E_OK Operation successful
if (!mbrId) return E_ARGUMENT ;
if (m_MemberUID) return E_DUPLICATE ;
m_MemberUID = mbrId ;
return E_OK ;
}
hzEcode hdbMember::_setOset (int32_t nOset) const
{
// Set Field Specification for the member. Relevant only to webapp forms. Not relevant to HDB operation.
//
// Argument: pSpec The supplied Dissemino field spec
//
// Returns: E_OK Operation always successful
m_nOsetStd = nOset ;
return E_OK ;
}
hzEcode hdbMember::_setAux (int32_t nAux) const
{
// Set Field Specification for the member. Relevant only to webapp forms. Not relevant to HDB operation.
//
// Argument: pSpec The supplied Dissemino field spec
//
// Returns: E_OK Operation always successful
m_nOsetAux = nAux ;
return E_OK ;
}
/*
** hdbClass Functions
*/
hdbClass::hdbClass (hdbADP& adp, hdbClsDgn designation)
{
// Data class constructor. Note the expectation that the data class will belong to a pre-existing ADP
m_pADP = &adp ;
m_arrMembers.SetDefault((hdbMember*)0) ;
m_eClassInit = HDB_CLASS_INIT_NONE ;
m_eDesignation = designation ;
m_nCoreLen = 0 ;
m_nLitmusBits = 0 ;
m_nLitmusSize = 0 ;
m_ClassUID = 0 ;
m_nBinaries = 0 ;
m_nArrays = 0 ;
m_Basetype = BASETYPE_CLASS ;
}
hdbClass::~hdbClass (void)
{
_clear() ;
}
void hdbClass::_clear (void)
{
// Private function to clear data object class descriptor. Note this is always assumed to be successful
//
// Arguments: None
// Returns: None
_hzfunc("hdbClass::_clear") ;
hdbMember* pMbr ; // Member pointer
uint32_t x ; // Member iterator
// We only need this because the hzArray is of pointers
for (x = 0 ; x < m_arrMembers.Count() ; x++)
{
pMbr = m_arrMembers[x] ;
if (pMbr)
delete pMbr ;
}
m_mapMembers.Clear() ;
m_arrMembers.Clear() ;
}
hzEcode hdbClass::_setId (uint32_t nId) const
{
// Set class UID.
//
// Argument: nId The supplied Dissemino field spec
//
// Returns: E_ARGUMENT If no field spec is supplied
// E_DUPLICATE If the field spec has already been set
// E_OK Operation successful
if (!nId) return E_ARGUMENT ;
if (m_ClassUID) return E_DUPLICATE ;
hzChain desc ; // For formulating class description (used as delta file header)
m_ClassUID = nId ;
DescClass(desc, 0) ;
m_Desc = desc ;
return E_OK ;
}
hzEcode hdbClass::InitStart (const hzString& className)
{
// Init Start function. This must be called only on a hdbClass instance that is not initialized and which is not in the process of being
// initialized.
//
// Arguments: 1) className The data class name
//
// Returns: E_ARGUMENT No row class object named
// E_INITFAIL Function called out of sequence: Must be first called and not repeated.
// E_MEMORY Insufficient memory
// E_OK Operation successful.
_hzfunc("hdbClass::InitStart") ;
// No Application Delta Profile?
if (!m_pADP)
return hzerr(E_NOINIT, "No Host ADP Found") ;
// No class name supplied?
if (!className)
return hzerr(E_ARGUMENT, "No name supplied") ;
// Data class already exists?
if (m_pADP->GetPureClass(className))
return hzerr(E_DUPLICATE, "hdbClass %s already exists", *className) ;
// Data class init already in progress?
if (m_eClassInit != HDB_CLASS_INIT_NONE)
return hzerr(E_INITFAIL, "Function called out of sequence: Must be first called and not repeated") ;
m_Typename = className ;
m_eClassInit = HDB_CLASS_INIT_PROG ;
return E_OK ;
}
hzEcode hdbClass::InitMember (const hzString& mbrName, const hdbDatatype* pType, hdbPopCtl popCtl)
{
// Adds a member to the data class
//
// Arguments: 1) mbrName Member name
// 2) type The external data type
// 3) popCtl Population restraints
//
// Returns: E_ARGUMENT If no member name is supplied
// E_DUPLICATE If a member of the supplied name already exists
// E_NOINIT If the InitStart() function has not yet been called
// E_SEQUENCE If the InitDone() function has been called
// E_OK If the member is successfully added
//
// Note: This function will terminate execution if the member could not be allocated.
_hzfunc("hdbClass::InitMember(1)") ;
const hdbClass* pSub ; // Sub-class if applicable
hdbMember* pMbr ; // The column
hzString S ; // Temp string
hzEcode rc ; // Return code
//if (m_eClassInit < 1 || m_eClassInit > 2)
if (m_eClassInit != HDB_CLASS_INIT_PROG)
return hzerr(E_INITFAIL, "Init state %d Called out of sequence (must be after InitStart() and before InitDone()", m_eClassInit) ;
// No Application Delta Profile?
if (!m_pADP)
return hzerr(E_NOINIT, "No Host ADP Found") ;
// No member name supplied?
if (!mbrName)
return hzerr(E_ARGUMENT, "No member name supplied") ;
// No member data type supplied?
if (!pType)
return hzerr(E_ARGUMENT, "No member data type supplies for %s", *mbrName) ;
// Data class member already exists?
if (GetMember(mbrName))
return hzerr(E_INITDUP, "Member (%s) already defined", *mbrName) ;
pMbr = new hdbMember() ;
if (!pMbr)
return hzerr(E_MEMORY, "Member allocation") ;
// Set up member
rc = pMbr->Init(this, pType, mbrName, m_arrMembers.Count(), popCtl) ;
if (rc != E_OK)
return hzerr(rc, "Please examine arguments for column [%s]", *mbrName) ;
m_mapMembers.Insert(mbrName, pMbr) ;
// Assign member ID
m_pADP->RegisterMember(pMbr) ;
// Put the member in the map and of columns
m_mapMembers.Insert(mbrName, pMbr) ;
m_arrMembers.Add(pMbr) ;
threadLog("Added member %s (of %d) to class %s\n", *mbrName, MbrCount(), txtType()) ;
// If member is a sub-class then put this in the m_mapSubs and all its subs
if (pMbr->IsClass())
{
pSub = (const hdbClass*) pMbr->Datatype() ;
m_pADP->NoteSub(strType(), pSub) ;
}
if (pMbr->Basetype() == BASETYPE_BINARY || pMbr->Basetype() == BASETYPE_TXTDOC)
m_nBinaries++ ;
if (pMbr->Multiple())
m_nArrays++ ;
m_eClassInit = HDB_CLASS_INIT_PROG ;
return E_OK ;
}
hzEcode hdbClass::InitMember (const hzString& mbrName, const hzString& typeName, hdbPopCtl popCtl)
{
_hzfunc("hdbClass::InitMember(2)") ;
const hdbDatatype* pDT ; // Data type
if (m_eClassInit != HDB_CLASS_INIT_PROG)
return hzerr(E_INITFAIL, "Init state %d Called out of sequence (must be after InitStart() and before InitDone()", m_eClassInit) ;
if (!m_pADP)
return hzerr(E_NOINIT, "No Host ADP Found") ;
pDT = m_pADP->GetDatatype(typeName) ;
if (!pDT)
return hzerr(E_NOTFOUND, "No such data type as %s", *typeName) ;
return InitMember(mbrName, pDT, popCtl) ;
}
hzEcode hdbClass::InitDone (void)
{
// Complete the initialization sequence.
//
// This is a mainly a matter of calculating how member space within hdbObject will be arranged. Members are assigned space that depends on the datatype and max population, and
// they are given relative positions that ensure the correct byte alignment. To this end the members are first sorted by datum size ...
//
// Arguments: None
//
// Returns: E_SEQUENCE If this function is not called after a successful InitStart() and InitMember()
// E_OK If this function terminates an open initialization sequence
_hzfunc("hdbClass::InitDone") ;
const hdbMember* pMbr ; // Member pointer
uint32_t mbrNo ; // Member number
uint32_t nSofar ; // For adding up total core space needed by all members
// Check init sequence
if (m_eClassInit != HDB_CLASS_INIT_PROG)
return hzerr(E_SEQUENCE, "Called out of sequence (must be after InitStart() and at least one call to InitMember()") ;
// Allocate member space within hdbObject core. Start with 16-byte entities if any, then 8, then 4. Leave ENUM till last as a special case.
nSofar = 0 ;
//m_nNonBool = 0 ;
// Allocate 16-byte slots
for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++)
{
pMbr = m_arrMembers[mbrNo] ;
if (pMbr->Basetype() == BASETYPE_ENUM)
continue ;
if (pMbr->SizeCore() < 16)
continue ;
pMbr->_setOset(nSofar) ;
nSofar += 16 ;
}
// Allocate 8-byte slots, including the aux slot for BINARY/TXTDOC members
for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++)
{
pMbr = m_arrMembers[mbrNo] ;
if (pMbr->Basetype() == BASETYPE_ENUM)
continue ;
if (pMbr->Basetype() == BASETYPE_BINARY || pMbr->Basetype() == BASETYPE_TXTDOC)
{
pMbr->_setAux(nSofar) ;
nSofar += 8 ;
continue ;
}
if (pMbr->SizeCore() != 8)
continue ;
pMbr->_setOset(nSofar) ;
nSofar += 8 ;
}
// Allocate 4-byte slots
for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++)
{
pMbr = m_arrMembers[mbrNo] ;
if (pMbr->Basetype() == BASETYPE_BINARY || pMbr->Basetype() == BASETYPE_TXTDOC)
{
// Allocate space for binary datum id
pMbr->_setOset(nSofar) ;
nSofar += 4 ;
continue ;
}
if (pMbr->Basetype() == BASETYPE_ENUM)
continue ;
if (pMbr->SizeCore() != 4)
continue ;
pMbr->_setOset(nSofar) ;
nSofar += 4 ;
}
// 2-byte allocations
for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++)
{
pMbr = m_arrMembers[mbrNo] ;
if (pMbr->Basetype() == BASETYPE_ENUM)
continue ;
if (pMbr->SizeCore() != 2)
continue ;
pMbr->_setOset(nSofar) ;
nSofar += 2 ;
}
// Enums
for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++)
{
pMbr = m_arrMembers[mbrNo] ;
if (pMbr->Basetype() != BASETYPE_ENUM)
continue ;
pMbr->_setOset(nSofar) ;
nSofar += pMbr->SizeCore() ;
}
// Bools
for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++)
{
pMbr = m_arrMembers[mbrNo] ;
if (pMbr->Basetype() == BASETYPE_BOOL)
continue ;
if (pMbr->Basetype() == BASETYPE_TBOOL)
{
//pMbr->_setOset(nSofar) ;
//nSofar += 1 ;
m_nLitmusBits++ ;
continue ;
}
//m_nNonBool++ ;
}
// Core len is total core size
m_nLitmusBits += m_arrMembers.Count() ;
m_nLitmusSize = m_nLitmusBits/8 ;
if (m_nLitmusBits%8)
m_nLitmusSize++ ;
m_nCoreLen = nSofar ;
// Report class form
for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++)
{
pMbr = m_arrMembers[mbrNo] ;
threadLog("Mbr %u %s: Posn %u Datum %u Core %u oset %d aux %d\n", mbrNo, pMbr->txtName(), pMbr->Posn(), pMbr->SizeDatum(), pMbr->SizeCore(), pMbr->OsetStd(), pMbr->OsetAux()) ;
}
threadLog("Class %s complete, core len %u\n", txtName(), m_nCoreLen) ;
// Move to Register Class
// hzChain desc ;
// DescClass(desc, 0) ;
// m_Desc = desc ;
// Indicate that class init is complete
m_eClassInit = HDB_CLASS_INIT_DONE ;
return E_OK ;
}
bool hdbClass::operator== (const hdbClass& op) const
{
// Test for equality between hdbClass instances (this row has same columns and column settings as the operand)
//
// Arguments: 1) op The operand data class
_hzfunc("hdbClass::operator==") ;
const hdbMember* pMA ; // Member pointer for this class
const hdbMember* pMB ; // Member pointer for other class
uint32_t nIndex ; // Member iterator
if (MbrCount() != op.MbrCount())
return false ;
for (nIndex = 0 ; nIndex < m_arrMembers.Count() ; nIndex++)
{
pMA = m_arrMembers[nIndex] ;
pMB = op.m_arrMembers[nIndex] ;
if (pMA != pMB)
return false ;
}
return true ;
}
/*
** SECTION 5: Application Delta Profile
*/
void hdbClass::DescClass (hzChain& Z, uint32_t nIndent) const
{
// Export Class Description
//
// Export XML fragment describing the data class to the supplied chain. Note that as the class description is expected to be part of an ADP, the supplied chain is not cleared
// by this function.
//
// Arguments: 1) Z The chain to aggregate the class description to
// 2) nIndent The number of leading tabs to apply to each line
//
// Returns: None
_hzfunc("hdbClass::DescClass") ;
const hdbDatatype* pType ; // Member data type
const hdbClass* pSubClass ; // Sub-class where member is BASETYPE_CLASS
const hdbMember* pMbr ; // Member pointer
uint32_t mbrNo ; // Member iterator
uint32_t n ; // Indent counter
for (n = nIndent ; n > 0 ; n--)
Z.AddByte(CHAR_TAB) ;
switch (m_eDesignation)
{
case HDB_CLASS_DESIG_SYS: Z.Printf("<class id=\"%d\" desig=\"sys\" name=\"%s\">\n", m_ClassUID, txtType()) ; break ;
case HDB_CLASS_DESIG_USR: Z.Printf("<class id=\"%d\" desig=\"usr\" name=\"%s\">\n", m_ClassUID, txtType()) ; break ;
case HDB_CLASS_DESIG_CFG: Z.Printf("<class id=\"%d\" desig=\"cfg\" name=\"%s\">\n", m_ClassUID, txtType()) ; break ;
}
for (mbrNo = 0 ; mbrNo < MbrCount() ; mbrNo++)
{
pMbr = GetMember(mbrNo) ;
for (n = nIndent ; n > 0 ; n--)
Z.AddByte(CHAR_TAB) ;
pType = pMbr->Datatype() ;
if (!pType)
{
Z.Printf("\t<member posn=\"%d\" uid=\"%d\" popCtl=\"%s\" datatype=\"INVALID_DATA_TYPE\" name=\"%s\"/>\n",
pMbr->Posn(), pMbr->DeltaId(), PopCtl2Txt(pMbr->PopCtl()), pMbr->txtName()) ;
continue ;
}
if (!pMbr->IsClass())
{
Z.Printf("\t<member posn=\"%d\" uid=\"%d\" popCtl=\"%s\" datatype=\"%s\" name=\"%s\"/>\n",
pMbr->Posn(), pMbr->DeltaId(), PopCtl2Txt(pMbr->PopCtl()), pType->txtType(), pMbr->txtName()) ;
continue ;
}
if (pMbr->Basetype() == BASETYPE_CLASS)
{
Z.Printf("\t<member posn=\"%d\" uid=\"%d\" popCtl=\"%s\" subclass=\"%s\" name=\"%s\">\n",
pMbr->Posn(), pMbr->DeltaId(), PopCtl2Txt(pMbr->PopCtl()), pType->txtType(), pMbr->txtName()) ;
pSubClass = (hdbClass*) pMbr->Datatype() ;
pSubClass->DescClass(Z, nIndent + 1) ;
for (n = nIndent ; n > 0 ; n--)
Z.AddByte(CHAR_TAB) ;
Z << "\t</member>\n" ;
continue ;
}
}
for (n = nIndent ; n > 0 ; n--)
Z.AddByte(CHAR_TAB) ;
Z << "</class>\n" ;
}
hzEcode hdbClass::DescCheck (hzChain& report, hzChain& desc) const
{
// Check Class Description
//
// With the class initialized, it is possible to check that a class description in a delta or other repository file, matches the class. The description is
// supplied as a hzChain which is obtained by reading the file or file header. This function loads the hzChain into an XML document and then extracts tags
// describing the class and its members.
//
// Write out XML fragment describing the data class to the supplied chain. Note that as the class description is likely to be part of an Application Delta
// Profile, the supplied chain is not pre-cleared by this function.
//
// Arguments: 1) report To report errors
// 2) desc The supplied description
//
// Returns: E_FORMAT If there are ANY descrepancies (details in report)
// E_OK If the description matches the class
//
// Read a <class> tag on behalf of the hdbADProfile::Import function.
_hzfunc("hdbClass::DescCheck") ;
const hdbDatatype* pType ; // Data type
hzDocXml doc ; // XML document
hzXmlNode* pRoot ; // XML root node
hzXmlNode* pN2 ; // Second level node
hzAttrset ai ; // Attribute iterator
hzString cname ; // Class name
hzString str_id ; // Member id
hzString str_uid ; // Member uid
hzString str_min ; // Member minPop
hzString str_max ; // Member minPop
hzString str_typ ; // Member data type
hzString str_sub ; // Member sub class
hzString str_nam ; // Member name
hzEcode rc = E_OK ; // Return code
int16_t n ; // Integer test value
// Load description into XML doc
rc = doc.Load(desc) ;
if (rc != E_OK)
{ report << "Could not load XML document with supplied description\n" ; return E_SYNTAX ; }
pRoot = doc.GetRoot() ;
if (!pRoot)
{ report << "No XML root found in supplied description\n" ; return E_SYNTAX ; }
if (!pRoot->NameEQ("class"))
{ report << "Expected first tag of <class>\n" ; return E_SYNTAX ; }
// Obtain <class> attributes
str_id = cname = (char*) 0 ;
for (ai = pRoot ; ai.Valid() ; ai.Advance())
{
if (ai.NameEQ("id")) str_id = ai.Value() ;
else if (ai.NameEQ("name")) cname = ai.Value() ;
else
{ rc = E_SYNTAX ; report.Printf("Line %d: <class> bad param %s=%s\n", pRoot->Line(), ai.Name(), ai.Value()) ; break ; }
}
// Check class name and id
if (!cname)
report << "No class name supplied\n" ;
else
{
if (cname != m_Typename)
report.Printf("Name mismatch. Class actual name is %s. Description names class as %s.\n", *m_Typename, *cname) ;
}
if (!str_id)
report << "No class id supplied\n" ;
else
{
if (!IsInteger(n, *str_id))
report.Printf("Illegal Class ID: Must be integer. (%s)\n", *str_id) ;
if (n != m_ClassUID)
report.Printf("Class Delta ID mismatch. Class actual %d: Description id is %s\n", m_ClassUID, *str_id) ;
}
// Read in members
for (pN2 = pRoot->GetFirstChild() ; pN2 ; pN2 = pN2->Sibling())
{
if (!pN2->NameEQ("member"))
{ report.Printf("<class> only <member> allowed. %s unexpected\n", pN2->txtName()) ; continue ; }
str_id = str_uid = str_min = str_max = str_typ = str_sub = str_nam = (char*) 0 ;
// Read in member parameters
for (ai = pN2 ; ai.Valid() ; ai.Advance())
{
if (ai.NameEQ("posn")) str_id = ai.Value() ;
else if (ai.NameEQ("uid")) str_uid = ai.Value() ;
else if (ai.NameEQ("min")) str_min = ai.Value() ;
else if (ai.NameEQ("max")) str_max = ai.Value() ;
else if (ai.NameEQ("datatype")) str_typ = ai.Value() ;
else if (ai.NameEQ("subclass")) str_sub = ai.Value() ;
else if (ai.NameEQ("name")) str_nam = ai.Value() ;
else
report.Printf("Line %d: <member> bad param %s=%s\n", pN2->Line(), ai.Name(), ai.Value()) ;
}
if (!str_id) report.Printf("No member position suplied (line %d)\n", pN2->Line()) ;
if (!str_uid) report.Printf("No member UID suplied (line %d)\n", pN2->Line()) ;
if (!str_min) report.Printf("No member min pop suplied (line %d)\n", pN2->Line()) ;
if (!str_max) report.Printf("No member max pop suplied (line %d)\n", pN2->Line()) ;
if (!str_nam) report.Printf("No member name suplied (line %d)\n", pN2->Line()) ;
if (!IsInteger(n, *str_id)) report.Printf("Illegal member position: Must be integer 0+ (line %d)\n", pN2->Line()) ;
if (!IsInteger(n, *str_uid)) report.Printf("Illegal member ID: Must be integer 0+ (line %d)\n", pN2->Line()) ;
if (!IsInteger(n, *str_min)) report.Printf("Illegal member min-POP: Must be integer 0+ (line %d)\n", pN2->Line()) ;
if (!IsInteger(n, *str_max)) report.Printf("Illegal member max-POP: Must be integer 0+ (line %d)\n", pN2->Line()) ;
if (!str_typ)
str_typ = str_sub ;
pType = m_pADP->GetDatatype(str_typ) ;
if (!pType)
report.Printf("<member> No such data type or sub-class as %s\n", pN2->Line(), *str_typ) ;
}
if (report.Size())
return E_FORMAT ;
return E_OK ;
}
void hdbObjRepos::DescRepos (hzChain& Z, uint32_t nIndent) const
{
// Export Repository Description
//
// Write out XML fragment describing the data repository to the supplied chain. Note that as the class description is likely to be part of an Application
// Delta Profile, the supplied chain is not pre-cleared by this function.
//
// Arguments: 1) Z The chain to aggregate the class description to
// 2) nIndent The number of leading tabs to apply to each line
//
// Returns: None
_hzfunc("hdbObjRepos::DescRepos") ;
}
hzEcode hdbADP::Export (void)
{
// Export the Application Delta Profile (ADP)
//
// The current ADP for any application using the HadronZoo Database Suite (HDB), will be in a file 'appname.adp' in the /etc/hzDelta.d directory.
_hzfunc("hdbADP::Export") ;
hzMapS <uint32_t,const hdbClass*> classesById ; // For ordering classes by ID
ofstream os ; // Output stream
ifstream is ; // Input stream for previous ADP if applicable
hzChain Z ; // For building the ADP
hzChain Y ; // Previous ADP
const hdbEnum* pEnum ; // Data enum
const hdbClass* pClass ; // Data class
hzString fname ; // Filename
hzString bkfile ; // Filename
uint32_t nC ; // Data class iterator
hzEcode rc = E_OK ; // Return code
fname = "/etc/hzDelta.d/" + m_appName + ".adp" ;
bkfile = "/etc/hzDelta.d/" + m_appName + ".bak" ;
threadLog("Exporting ADP to %s\n", *fname) ;
if (TestFile(*fname) == E_OK)
{
is.open(*fname) ;
Y << is ;
is.close() ;
}
Z.Printf("<AppDeltaProfile app=\"%s\">\n", *m_appName) ;
for (nC = 0 ; nC < m_mapEnums.Count() ; nC++)
{
pEnum = m_mapEnums.GetObj(nC) ;
Z.Printf("\t<enum name=\"%s\"/>\n", pEnum->txtType()) ;
}
for (nC = 0 ; nC < m_mapClasses.Count() ; nC++)
{
pClass = m_mapClasses.GetObj(nC) ;
classesById.Insert(pClass->ClassId(), pClass) ;
}
for (nC = 0 ; nC < classesById.Count() ; nC++)
{
pClass = classesById.GetObj(nC) ;
pClass->DescClass(Z, 1) ;
}
Z << "</AppDeltaProfile>\n" ;
if (Y.Size())
{
if (Y == Z)
{ threadLog("ADP is an exact match\n") ; return E_OK ; }
threadLog("Backing up ADP\n") ;
Filecopy(*bkfile, *fname) ;
}
threadLog("Exporting current ADP\n") ;
os.open(*fname) ;
os << Z ;
os.close() ;
return rc ;
}
hzEcode hdbADP::_rdClass (hzXmlNode* pN)
{
// Read a <class> tag on behalf of the hdbADProfile::Import function.
_hzfunc("hdbADProfile::_readClass") ;
const hdbDatatype* pType ; // Data type
hdbClass* pClass ; // Data class
hzXmlNode* pN2 ; // Second level node
hzAttrset ai ; // Attribute iterator
hzString cname ; // Class name
hzString desig ; // Class designation
hzString str_id ; // Member id
hzString str_uid ; // Member uid
hzString str_pop ; // Member population control as string
hzString str_typ ; // Member data type
hzString str_sub ; // Member sub class
hzString str_nam ; // Member name
hdbPopCtl popCtl ; // Member population control as enum
hzEcode rc = E_OK ; // Return code
if (!pN->NameEQ("class"))
return E_SYNTAX ;
str_id = cname = (char*) 0 ;
for (ai = pN ; ai.Valid() ; ai.Advance())
{
if (ai.NameEQ("id")) str_id = ai.Value() ;
else if (ai.NameEQ("desig")) desig = ai.Value() ;
else if (ai.NameEQ("name")) cname = ai.Value() ;
else
{ rc = E_SYNTAX ; threadLog("Line %d: <class> bad param %s=%s\n", pN->Line(), ai.Name(), ai.Value()) ; break ; }
}
if (!cname) return hzerr(E_ARGUMENT, "No class name supplied") ;
if (!desig) return hzerr(E_ARGUMENT, "No class designation supplied") ;
if (desig == "sys") pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ;
else if (desig == "usr") pClass = new hdbClass(*this, HDB_CLASS_DESIG_USR) ;
else if (desig == "cfg") pClass = new hdbClass(*this, HDB_CLASS_DESIG_CFG) ;
else
return hzerr(E_ARGUMENT, "Invalid class designation supplied (%s). Must be sys|usr|cfg") ;
pClass->InitStart(cname) ;
threadLog("Reading class %s\n", *cname) ;
m_mapDatatypes.Insert(cname, pClass) ;
m_mapClasses.Insert(cname, pClass) ;
// Read in member parameters
for (pN2 = pN->GetFirstChild() ; pN2 ; pN2 = pN2->Sibling())
{
if (!pN2->NameEQ("member"))
{ rc = E_SYNTAX ; threadLog("Line %d: <class> only <member> allowed. %s unexpected\n", pN2->Line(), pN2->txtName()) ; break ; }
str_id = str_uid = str_pop = str_typ = str_sub = str_nam = (char*) 0 ;
for (ai = pN2 ; ai.Valid() ; ai.Advance())
{
if (ai.NameEQ("posn")) str_id = ai.Value() ;
else if (ai.NameEQ("uid")) str_uid = ai.Value() ;
else if (ai.NameEQ("pop")) str_pop = ai.Value() ;
else if (ai.NameEQ("datatype")) str_typ = ai.Value() ;
else if (ai.NameEQ("subclass")) str_sub = ai.Value() ;
else if (ai.NameEQ("name")) str_nam = ai.Value() ;
else
{ rc = E_SYNTAX ; threadLog("Line %d: <member> bad param %s=%s\n", pN2->Line(), ai.Name(), ai.Value()) ; break ; }
}
if (!str_typ)
str_typ = str_sub ;
pType = m_mapDatatypes[str_typ] ;
if (!pType)
{ rc = E_NOTFOUND ; threadLog("Line %d: <member> No such data type as %s\n", pN2->Line(), *str_typ) ; break ; }
if (str_pop == "SingleOptional") popCtl = HDB_MBR_POP_SINGLE_OPTIONAL ;
else if (str_pop == "SingleCompulsory") popCtl = HDB_MBR_POP_SINGLE_COMPULSORY ;
else if (str_pop == "ArrayOptional") popCtl = HDB_MBR_POP_SINGLE_COMPULSORY ;
else if (str_pop == "ArrayCompulsory") popCtl = HDB_MBR_POP_SINGLE_COMPULSORY ;
else
{
rc = E_SYNTAX ;
threadLog("Line %d: Population control must be either SingleOptional, SingleCompulsory, ArrayOptional or ArrayCompulsory. %s not accepted\n", *str_pop) ;
}
pClass->InitMember(str_nam, pType, popCtl) ;
}
pClass->InitDone() ;
return rc ;
}
hzEcode hdbADP::Import (const hzString& appName)
{
// Import the Application Delta Profile (ADP), of the named application.
//
// The current ADP for any application using the HadronZoo Database Suite (HDB), will be in a file 'appname.adp' in the /etc/hzDelta.d directory.
_hzfunc("hdbADP::Import") ;
hzArray <hzString> ar ; // Enum values
ifstream is ; // Input stream for previous ADP if applicable
hzDocXml docADP ; // XML document
hzChain Z ; // For building the ADP
hzChain Y ; // Previous ADP
hzXmlNode* pRoot ; // Document root node
hzXmlNode* pN ; // First level node
hzAttrset ai ; // Attribute iterator
hdbEnum* pEnum ; // Data enum
hzString fname ; // Filename
hzString bkfile ; // Filename
hzString cname ; // Class name
hzString str_id ; // Member id
hzString str_uid ; // Member uid
hzString str_min ; // Member minPop
hzString str_max ; // Member minPop
hzString str_typ ; // Member data type
hzString str_sub ; // Member sub class
hzString str_nam ; // Member name
hzString S ; // Temp string (enum values)
uint32_t n ; // Enum value iterator
hzEcode rc = E_OK ; // Return code
fname = "/etc/hzDelta.d/" + appName + ".adp" ;
if (TestFile(*fname) == E_OK)
{
is.open(*fname) ;
Y << is ;
is.close() ;
}
rc = docADP.Load(*fname) ;
if (rc != E_OK)
{
threadLog("Could not load ADP document (%s)\n", *fname) ;
threadLog(docADP.Error()) ;
return rc ;
}
pRoot = docADP.GetRoot() ;
if (!pRoot)
{
threadLog("ADP document (%s) has no route\n", *fname) ;
return E_NOINIT ;
}
for (pN = pRoot->GetFirstChild() ; pN ; pN = pN->Sibling())
{
if (pN->NameEQ("enum"))
{
for (ai = pN ; ai.Valid() ; ai.Advance())
{
if (ai.NameEQ("name"))
str_nam = ai.Value() ;
else
{ rc = E_SYNTAX ; threadLog("Line %d: <enum> bad param %s=%s\n", pN->Line(), ai.Name(), ai.Value()) ; break ; }
}
pEnum = new hdbEnum() ;
pEnum->SetTypename(str_nam) ;
// Add to data types
m_mapDatatypes.Insert(str_nam, pEnum) ;
m_mapEnums.Insert(str_nam, pEnum) ;
SplitCSV(ar, pN->m_fixContent) ;
for (n = 0 ; n < ar.Count() ; n++)
{
S = ar[n] ;
// if (S.Length() > pEnum->m_nMax)
// pEnum->m_nMax = S.Length() ;
//pEnum->m_Numbers.Add(strNo) ;
pEnum->AddItem(S) ;
}
}
else if (pN->NameEQ("class"))
{
rc = _rdClass(pN) ;
if (rc != E_OK)
break ;
}
}
return rc ;
}
hzEcode hdbADP::InitStandard (const hzString& appName)
{
// Add the fundamental C++ and the HadronZoo in-built data types to the global map of datatypes _hzGlobal_Datatypes.
//
// Arguments: None
//
// Returns: E_SEQUENCE If this function has already been called
// E_OK Otherwise.
_hzfunc("hdbADP::InitStandard") ;
hdbCpptype* ct ; // Pointer to Cpp data type
hdbHzotype* ht ; // Pointer to Cpp data type
if (!this)
Fatal("No ADP Instance") ;
if (m_appName)
Fatal("This function has already been called setting app name to ") ;
if (!appName)
return hzerr(E_ARGUMENT, "No application name supplied") ;
m_appName = appName ;
// Group 1: C++ Fundamental types
datatype_DIGEST = ct = new hdbCpptype() ; ct->SetTypename("hashMD5"); ct->SetBasetype(BASETYPE_DIGEST); m_mapDatatypes.Insert(ct->strType(), ct);
datatype_DOUBLE = ct = new hdbCpptype() ; ct->SetTypename("double"); ct->SetBasetype(BASETYPE_DOUBLE); m_mapDatatypes.Insert(ct->strType(), ct);
datatype_INT64 = ct = new hdbCpptype() ; ct->SetTypename("int64"); ct->SetBasetype(BASETYPE_INT64); m_mapDatatypes.Insert(ct->strType(), ct);
datatype_INT32 = ct = new hdbCpptype() ; ct->SetTypename("int32"); ct->SetBasetype(BASETYPE_INT32); m_mapDatatypes.Insert(ct->strType(), ct);
datatype_INT16 = ct = new hdbCpptype() ; ct->SetTypename("int16"); ct->SetBasetype(BASETYPE_INT16); m_mapDatatypes.Insert(ct->strType(), ct);
datatype_BYTE = ct = new hdbCpptype() ; ct->SetTypename("byte"); ct->SetBasetype(BASETYPE_BYTE); m_mapDatatypes.Insert(ct->strType(), ct);
datatype_UINT64 = ct = new hdbCpptype() ; ct->SetTypename("uint64"); ct->SetBasetype(BASETYPE_UINT64); m_mapDatatypes.Insert(ct->strType(), ct);
datatype_UINT32 = ct = new hdbCpptype() ; ct->SetTypename("uint32"); ct->SetBasetype(BASETYPE_UINT32); m_mapDatatypes.Insert(ct->strType(), ct);
datatype_UINT16 = ct = new hdbCpptype() ; ct->SetTypename("uint16"); ct->SetBasetype(BASETYPE_UINT16); m_mapDatatypes.Insert(ct->strType(), ct);
datatype_UBYTE = ct = new hdbCpptype() ; ct->SetTypename("ubyte"); ct->SetBasetype(BASETYPE_UBYTE); m_mapDatatypes.Insert(ct->strType(), ct);
datatype_BOOL = ct = new hdbCpptype() ; ct->SetTypename("bool"); ct->SetBasetype(BASETYPE_BOOL); m_mapDatatypes.Insert(ct->strType(), ct);
// Group 2: HadronZoo in-built
datatype_DOMAIN = ht = new hdbHzotype() ; ht->SetTypename("domain"); ht->SetBasetype(BASETYPE_DOMAIN); m_mapDatatypes.Insert(ht->strType(), ht);
datatype_EMADDR = ht = new hdbHzotype() ; ht->SetTypename("emaddr"); ht->SetBasetype(BASETYPE_EMADDR); m_mapDatatypes.Insert(ht->strType(), ht);
datatype_URL = ht = new hdbHzotype() ; ht->SetTypename("url"); ht->SetBasetype(BASETYPE_URL); m_mapDatatypes.Insert(ht->strType(), ht);
datatype_IPADDR = ht = new hdbHzotype() ; ht->SetTypename("ipaddr"); ht->SetBasetype(BASETYPE_IPADDR); m_mapDatatypes.Insert(ht->strType(), ht);
datatype_TIME = ht = new hdbHzotype() ; ht->SetTypename("time"); ht->SetBasetype(BASETYPE_TIME); m_mapDatatypes.Insert(ht->strType(), ht);
datatype_SDATE = ht = new hdbHzotype() ; ht->SetTypename("sdate"); ht->SetBasetype(BASETYPE_SDATE); m_mapDatatypes.Insert(ht->strType(), ht);
datatype_XDATE = ht = new hdbHzotype() ; ht->SetTypename("xdate"); ht->SetBasetype(BASETYPE_XDATE); m_mapDatatypes.Insert(ht->strType(), ht);
datatype_STRING = ht = new hdbHzotype() ; ht->SetTypename("string"); ht->SetBasetype(BASETYPE_STRING); m_mapDatatypes.Insert(ht->strType(), ht);
datatype_TEXT = ht = new hdbHzotype() ; ht->SetTypename("text"); ht->SetBasetype(BASETYPE_TEXT); m_mapDatatypes.Insert(ht->strType(), ht);
datatype_BINARY = ht = new hdbHzotype() ; ht->SetTypename("binary"); ht->SetBasetype(BASETYPE_BINARY); m_mapDatatypes.Insert(ht->strType(), ht);
datatype_TXTDOC = ht = new hdbHzotype() ; ht->SetTypename("txtdoc"); ht->SetBasetype(BASETYPE_TXTDOC); m_mapDatatypes.Insert(ht->strType(), ht);
return E_OK ;
}
hzEcode hdbADP::InitSubscribers (const hzString& dataDir)
{
// Create the subscriber data class and repository
_hzfunc("hdbADP::InitSubscribers") ;
//hdbObjRepos* pRepos ; // Subscriber repository pointer
hzString S ; // Temporary string
hzEcode rc = E_OK ; // Return code
if (!this)
hzexit(E_CORRUPT, "No ADP instance") ;
if (m_pClassSubscriber)
rc = hzerr(E_DUPLICATE, "Subscriber class already declared") ;
S = "subscriber" ;
if (m_mapRepositories.Exists(S))
rc = hzerr(E_DUPLICATE, "This function has already been called") ;
if (!dataDir)
rc = hzerr(E_ARGUMENT, "No application data directory") ;
if (rc != E_OK)
return rc ;
// Allocate and initialize subscriber class
m_pClassSubscriber = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ;
rc = m_pClassSubscriber->InitStart(S) ;
if (rc == E_OK) { S = "username" ; rc = m_pClassSubscriber->InitMember(S, datatype_STRING, HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { S = "userpass" ; rc = m_pClassSubscriber->InitMember(S, datatype_STRING, HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { S = "userEmail" ; rc = m_pClassSubscriber->InitMember(S, datatype_EMADDR, HDB_MBR_POP_SINGLE_OPTIONAL) ; }
if (rc == E_OK) { S = "userUID" ; rc = m_pClassSubscriber->InitMember(S, datatype_UINT32, HDB_MBR_POP_SINGLE_OPTIONAL) ; }
if (rc == E_OK) { S = "userType" ; rc = m_pClassSubscriber->InitMember(S, datatype_STRING, HDB_MBR_POP_SINGLE_OPTIONAL) ; }
if (rc == E_OK)
{
rc = m_pClassSubscriber->InitDone() ;
// Obtain member pointers
m_pMbr_Subscriber_username = m_pClassSubscriber->GetMember(0) ;
m_pMbr_Subscriber_userpass = m_pClassSubscriber->GetMember(1) ;
m_pMbr_Subscriber_email = m_pClassSubscriber->GetMember(2) ;
m_pMbr_Subscriber_UID = m_pClassSubscriber->GetMember(3) ;
m_pMbr_Subscriber_type = m_pClassSubscriber->GetMember(4) ;
}
// Resister subscriber class
if (rc == E_OK)
rc = RegisterDataClass(m_pClassSubscriber) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber class") ;
// Create and initialize susscriber repository
m_pReposSubscriber = new hdbObjRepos(*this) ;
if (!m_pReposSubscriber)
hzexit(E_MEMORY, "No subsciber cache allocated") ;
rc = m_pReposSubscriber->InitStart(m_pClassSubscriber, m_pClassSubscriber->strName(), dataDir, HDB_REPOS_CACHE) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos") ;
//S = "username" ;
rc = m_pReposSubscriber->InitMbrIndex(m_pMbr_Subscriber_username, true) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos index") ;
rc = m_pReposSubscriber->InitDone() ;
if (rc != E_OK)
hzexit(rc, "Could not complete subsriber repos initialization") ;
// Resister subscriber repository
rc = m_mapRepositories.Insert(m_pReposSubscriber->strName(), m_pReposSubscriber) ;
/*
if (rc == E_OK)
{
m_pMbr_Subscriber_username = m_pClassSubscriber->GetMember(0) ;
m_pMbr_Subscriber_userpass = m_pClassSubscriber->GetMember(1) ;
m_pMbr_Subscriber_email = m_pClassSubscriber->GetMember(2) ;
m_pMbr_Subscriber_UID = m_pClassSubscriber->GetMember(3) ;
m_pMbr_Subscriber_type = m_pClassSubscriber->GetMember(4) ;
}
*/
return rc ;
}
hzEcode hdbADP::InitSiteIndex (const hzString& dataDir)
{
// The site index is an optional free text index for webapps that comes as standard. If deployed, it maps each word found within webapp page and article content, to the set of
// pages and articles in which the word appears. It is implemented directly as a hdbIndexText instance, without involving a data class or a data class repository.
_hzfunc("hdbADP::InitSiteIndex") ;
hdbClass* pClass ; // Subscriber class pointer
hdbObjRepos* pRepos ; // Subscriber repository pointer
hzString S ; // Temporary string
hzEcode rc ; // Return code
if (!this) hzexit(E_CORRUPT, "No ADP instance") ;
if (m_pSiteindex) return hzerr(E_SEQUENCE, "This function has already been called") ;
if (!dataDir) return hzerr(E_ARGUMENT, "No application data directory") ;
S = "siteindex" ;
m_pSiteindex = new hdbIndexText() ;
// Allocate and initialize subscriber class
pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ;
rc = pClass->InitStart(S) ;
if (rc == E_OK) { S = "pageUrl" ; rc = pClass->InitMember(S, datatype_STRING, HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { S = "PageTitle" ; rc = pClass->InitMember(S, datatype_STRING, HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK)
{
rc = pClass->InitDone() ;
}
// Resister subscriber class
if (rc == E_OK)
rc = RegisterDataClass(pClass) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber class") ;
// Create and initialize susscriber repository
pRepos = new hdbObjRepos(*this) ;
if (!pRepos)
hzexit(E_MEMORY, "No subsciber cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos") ;
S = "pageUrl" ;
rc = pRepos->InitMbrIndex(S, true) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ;
if (rc != E_OK)
hzexit(rc, "Could not complete subsriber repos initialization") ;
threadLog("Complete subsriber repos initialization") ;
// Resister subscriber repository
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ;
threadLog("Subscriber Repos Reg complete\n") ;
return rc ;
}
#if 0
hzEcode hdbADP::InitSearch (void)
{
// Create the search data class
_hzfunc("hdbADP::InitSearch") ;
static bool bBeenHere = false ; // Set once run
hdbClass* pClass ; // Subscriber class pointer
hzString S ; // Temporary string
hzEcode rc ; // Return code
if (bBeenHere)
return hzerr(E_SEQUENCE, "This function has already been called") ;
bBeenHere = true ;
// Allocate and initialize subscriber class
S = "sitesrch" ;
pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ;
rc = pClass->InitStart(S) ;
if (rc == E_OK)
{ S = "criteria" ; rc = pClass->InitMember(S, datatype_STRING, 1, 1) ; }
if (rc == E_OK)
rc = pClass->InitDone() ;
// Resister subscriber class
if (rc == E_OK)
rc = RegisterDataClass(pClass) ;
if (rc != E_OK)
hzexit(rc, "Could not init sitesrch class") ;
return E_OK ;
}
#endif
hzEcode hdbADP::InitFinancials (const hzString& dataDir)
{
_hzfunc("hdbADP::InitFinancials") ;
hdbEnum* pEnum ; // Enum pointer
hdbClass* pClass ; // Data class pointer
hdbObjRepos* pRepos ; // Repository pointer
hzString cname ; // Current data class name
hzString mname ; // Current member name
hzEcode rc ; // Return code
cname = "Currency" ;
if (m_mapRepositories.Exists(cname))
return hzerr(E_SEQUENCE, "This function has already been called") ;
if (!dataDir)
return hzerr(E_ARGUMENT, "No application data directory") ;
// Setup the 'Account Type' enum
mname = "enumAccType" ;
pEnum = new hdbEnum() ;
pEnum->SetTypename(mname) ;
pEnum->AddItem("ACC_NULL", 0x0000) ;
pEnum->AddItem("ACC_ASSET", 0x0001) ;
pEnum->AddItem("ACC_BANK", 0x0002) ;
pEnum->AddItem("ACC_CASH", 0x0004) ;
pEnum->AddItem("ACC_DIRECTOR", 0x0008) ;
pEnum->AddItem("ACC_FOREX", 0x0010) ;
pEnum->AddItem("ACC_GOV", 0x0020) ;
pEnum->AddItem("ACC_SHARE", 0x0040) ;
pEnum->AddItem("ACC_STOCK", 0x0080) ;
pEnum->AddItem("ACC_TRADE", 0x0100) ;
RegisterDataEnum(pEnum) ;
/*
** Currencies
*/
// Set up Currency data class
pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ;
rc = pClass->InitStart(cname) ;
if (rc == E_OK) { mname = "Name" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Symbol" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
rc = pClass->InitDone() ;
if (rc == E_OK)
rc = RegisterDataClass(pClass) ;
// Create and initialize Currency repository
pRepos = new hdbObjRepos(*this) ;
if (!pRepos)
hzexit(E_MEMORY, "No Currency cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos") ;
mname = "Name" ;
rc = pRepos->InitMbrIndex(mname, true) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ;
if (rc != E_OK)
hzexit(rc, "Could not complete subsriber repos initialization") ;
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ;
pRepos->Open() ;
/*
** Categories
*/
// Set up Currency data class
cname = "Category" ;
pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ;
rc = pClass->InitStart(cname) ;
if (rc == E_OK) { mname = "Code" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Desc" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
rc = pClass->InitDone() ;
if (rc == E_OK)
rc = RegisterDataClass(pClass) ;
// Create and initialize Currency repository
pRepos = new hdbObjRepos(*this) ;
if (!pRepos)
hzexit(E_MEMORY, "No Currency cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos") ;
mname = "Code" ;
rc = pRepos->InitMbrIndex(mname, true) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ;
if (rc != E_OK)
hzexit(rc, "Could not complete subsriber repos initialization") ;
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ;
pRepos->Open() ;
/*
** Accounts
*/
// Set up Account data class
cname = "Account" ;
pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ;
rc = pClass->InitStart(cname) ;
if (rc == E_OK) { mname = "Opened" ; rc = pClass->InitMember(mname, "sdate", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Closed" ; rc = pClass->InitMember(mname, "sdate", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Currency" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Code" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Desc" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "InitBal" ; rc = pClass->InitMember(mname, "int32", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Type" ; rc = pClass->InitMember(mname, "enumAccType", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
rc = pClass->InitDone() ;
if (rc == E_OK)
RegisterDataClass(pClass) ;
// Create and initialize Account repository
pRepos = new hdbObjRepos(*this) ;
if (!pRepos)
hzexit(E_MEMORY, "No Currency cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos") ;
mname = "Code" ;
rc = pRepos->InitMbrIndex(mname, true) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ;
if (rc != E_OK)
hzexit(rc, "Could not complete subsriber repos initialization") ;
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ;
pRepos->Open() ;
/*
** Transactions
*/
// Set up Transaction data class
cname = "Transaction" ;
pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ;
rc = pClass->InitStart(cname) ;
if (rc == E_OK) { mname = "Date" ; rc = pClass->InitMember(mname, "sdate", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Currency" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Category" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "From" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "To" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Desc" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Note" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Qty" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Value" ; rc = pClass->InitMember(mname, "int32", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK) { mname = "Type" ; rc = pClass->InitMember(mname, "int32", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
rc = pClass->InitDone() ;
if (rc == E_OK)
RegisterDataClass(pClass) ;
// Create and initialize Transaction repository
pRepos = new hdbObjRepos(*this) ;
if (!pRepos)
hzexit(E_MEMORY, "No Currency cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos") ;
mname = "Date" ;
rc = pRepos->InitMbrIndex(mname, true) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos index") ;
mname = "From" ;
rc = pRepos->InitMbrIndex(mname, true) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ;
if (rc != E_OK)
hzexit(rc, "Could not complete subsriber repos initialization") ;
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ;
pRepos->Open() ;
return rc ;
}
hzEcode hdbADP::InitBlockedIPs (const hzString& dataDir)
{
// Create the Blocked-IP data class and repository
_hzfunc("hdbADP::InitBlockedIPs") ;
static bool bBeenHere = false ; // Set once run
hdbClass* pClass ; // Subscriber class pointer
hdbObjRepos* pRepos ; // Subscriber repository pointer
hzString S ; // Temporary string
hzEcode rc ; // Return code
if (bBeenHere)
return hzerr(E_SEQUENCE, "This function has already been called") ;
bBeenHere = true ;
if (!dataDir)
return hzerr(E_ARGUMENT, "No application data directory") ;
// Allocate and initialize subscriber class
S = "blockedIP" ;
pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ;
rc = pClass->InitStart(S) ;
if (rc == E_OK) { S = "ipa" ; rc = pClass->InitMember(S, datatype_IPADDR, HDB_MBR_POP_SINGLE_COMPULSORY) ; }
if (rc == E_OK)
rc = pClass->InitDone() ;
// Resister subscriber class
if (rc == E_OK)
RegisterDataClass(pClass) ;
if (rc != E_OK)
hzexit(rc, "Could not init blockedIP class") ;
// Create and initialize susscriber repository
pRepos = new hdbObjRepos(*this) ;
if (!pRepos)
hzexit(E_MEMORY, "No blockedIP cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ;
if (rc != E_OK)
hzexit(rc, "Could not init blockedIP repos") ;
S = "ipa" ;
rc = pRepos->InitMbrIndex(S, true) ;
if (rc != E_OK)
hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ;
if (rc != E_OK)
hzexit(rc, "Could not complete subsriber repos initialization") ;
// Resister subscriber repository
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ;
return rc ;
}
void hdbADP::Report (hzChain& Z)
{
// Write out ADP
//
// Diagnostics
//
// Argument: Z Output chain
//
// Returns: None
_hzfunc("hdbADP::Report") ;
const hdbDatatype* pDT ; // Data type
const hdbClass* pClass ; // Data class
const hdbMember* pMbr ; // Data class member
hdbEnum* pSlct ; // Data enum
uint32_t x ; // General iterator
uint32_t y ; // General iterator
Z.Printf("APPLICATION DELTA PROFILE\n") ;
// Z.Printf("User Categories\n") ;
// for (x = 0 ; x < m_UserTypes.Count() ; x++)
// { ut = m_UserTypes.GetObj(x) ; Z.Printf(" -- %s\n", *ut.m_Refname) ; }
Z.Printf("Data types\n") ;
Z.Printf(" -- Validation formats\n") ;
for (x = 0 ; x < m_mapDatatypes.Count() ; x++)
{
pDT = m_mapDatatypes.GetObj(x) ;
if (pDT->Basetype() != BASETYPE_APPDEF)
continue ;
Z.Printf("\t -- %s\n", pDT->txtType()) ;
}
Z.Printf(" -- Selectors\n") ;
for (x = 0 ; x < m_mapDatatypes.Count() ; x++)
{
pDT = m_mapDatatypes.GetObj(x) ;
if (pDT->Basetype() != BASETYPE_ENUM)
continue ;
pSlct = (hdbEnum*) pDT ;
Z.Printf("\t -- %s\n", pSlct->txtType()) ;
}
Z.Printf(" -- Clases\n") ;
for (x = 0 ; x < m_mapClasses.Count() ; x++)
{
pClass = m_mapClasses.GetObj(x) ;
Z.Printf("\t -- %s\n", pClass->txtType()) ;
for (y = 0 ; y < pClass->MbrCount() ; y++)
{
pMbr = pClass->GetMember(y) ;
Z.Printf("\t\t -- %s [%s]\n", pMbr->txtName(), Basetype2Txt(pMbr->Basetype())) ;
}
}
Z.Printf(" -- Class Delta ID assignments\n") ;
for (x = 0 ; x < m_mapClsCtxDtId.Count() ; x++)
{
y = m_mapClsCtxDtId.GetKey(x) ;
pClass = m_mapClsCtxDtId.GetObj(x) ;
Z.Printf("\t\t -- [%d] %s\n", y, pClass->txtType()) ;
}
}
hzEcode hdbADP::RegisterDataClass (const hdbClass* pClass)
{
// Insert a new data class into the ADP. This may only be done during initialization.
//
// Argument: pClass The data class to be inserted
_hzfunc("hdbADP::RegisterDataClass") ;
if (!this)
hzexit(E_CORRUPT, "No ADP instance") ;
// No data class?
if (!pClass)
return E_ARGUMENT ;
// Unnamed data class?
if (!pClass->strType())
return E_NOINIT ;
// Data class already has delta id?
if (pClass->ClassId())
return hzerr(E_DUPLICATE, "Data class %s already registered with id %d", pClass->txtType(), pClass->ClassId()) ;
// Data type already registered?
if (m_mapDatatypes.Exists(pClass->strType()))
return hzerr(E_DUPLICATE, "Data type %s already registered. Cannot admit class of this name", pClass->txtType()) ;
// Allocate the class id
switch (pClass->Designation())
{
case HDB_CLASS_DESIG_SYS: if (pClass->strType() == "subscriber") pClass->_setId(HZ_ADP_CLS_SUBSCRIBER) ;
else if (pClass->strType() == "siteindex") pClass->_setId(HZ_ADP_CLS_SITEINDEX) ;
else if (pClass->strType() == "FinCurrency") pClass->_setId(HZ_ADP_CLS_FIN_CRCY) ;
else if (pClass->strType() == "FinCategory") pClass->_setId(HZ_ADP_CLS_FIN_CAT) ;
else if (pClass->strType() == "FinAccount") pClass->_setId(HZ_ADP_CLS_FIN_ACC) ;
else if (pClass->strType() == "FinTransaction") pClass->_setId(HZ_ADP_CLS_FIN_TRNS) ;
else
{
hzerr(E_BADVALUE, "Unrecognized System Class (%s)", pClass->txtType()) ;
return E_BADVALUE ;
}
break ;
case HDB_CLASS_DESIG_USR: pClass->_setId(m_nsqClsUsr++) ;
break ;
case HDB_CLASS_DESIG_CFG: pClass->_setId(m_nsqClsCfg++) ;
break ;
}
if (!pClass->ClassId())
return hzerr(E_NOINIT, "Data class %s did not aquire a delta id", pClass->txtType()) ;
// Insert data class into ADP map of datatypes
m_mapDatatypes.Insert(pClass->strType(), pClass) ;
m_mapClasses.Insert(pClass->strType(), pClass) ;
m_mapClsCtxName.Insert(pClass->strType(), pClass->ClassId()) ; //m_mapClasses.Count()) ;
m_mapClsCtxDtId.Insert(pClass->ClassId(), pClass) ;
threadLog("Inserted %s\n", *pClass->strType()) ;
return E_OK ;
}
hzEcode hdbADP::RegisterComposite (hzString& context, const hdbClass* pClass)
{
// Insert a new data class context into the ADP. This may only be done during initialization.
//
// Argument: pClass The data class to be inserted
_hzfunc("hdbADP::RegisterComposite") ;
if (!context || !pClass)
return E_ARGUMENT ;
m_mapClsCtxName.Insert(context, m_nsqClsCtx) ;
m_mapClsCtxDtId.Insert(m_nsqClsCtx, pClass) ;
m_nsqClsCtx++ ;
return E_OK ;
}
hzEcode hdbADP::RegisterMember (const hdbMember* pMbr)
{
_hzfunc("hdbADP::RegisterMember") ;
const hdbClass* pClass ; // Data class of member
uint32_t mbrId ; // Member ID to be
pClass = pMbr->Class() ;
if (!pClass)
hzexit(E_NOINIT, "Member not initialized to its host data class") ;
// Assign member ID
switch (pClass->Designation())
{
case HDB_CLASS_DESIG_SYS: mbrId = m_nsqMbrSys++ ; break ;
case HDB_CLASS_DESIG_USR: mbrId = m_nsqMbrUsr++ ; break ;
case HDB_CLASS_DESIG_CFG: mbrId = m_nsqMbrCfg++ ; break ;
}
m_mapMembers.Insert(mbrId, pMbr) ;
pMbr->_setId(mbrId) ;
return E_OK ;
}
hzEcode hdbADP::RegisterDataEnum (const hdbEnum* pEnum)
{
// Insert a new data enum into the ADP. This may only be done during initialization.
//
_hzfunc("hdbADP::RegisterDataEnum") ;
if (!pEnum)
return E_ARGUMENT ;
if (!pEnum->strType())
return E_NOINIT ;
m_mapDatatypes.Insert(pEnum->strType(), pEnum) ;
m_mapEnums.Insert(pEnum->strType(), pEnum) ;
return E_OK ;
}
hzEcode hdbADP::RegisterRegexType (const hdbRgxtype* pRgx)
{
_hzfunc("hdbADP::RegisterRegexType") ;
if (!pRgx)
return E_ARGUMENT ;
if (!pRgx->strType())
return E_NOINIT ;
return m_mapDatatypes.Insert(pRgx->strType(), pRgx) ;
}
hzEcode hdbADP::RegisterObjRepos (hdbObjRepos* pRepos)
{
_hzfunc("hdbADP::RegisterObjRepos") ;
hzEcode rc ; // Return code
if (!pRepos)
return E_ARGUMENT ;
if (!pRepos->strName())
return E_NOINIT ;
if (m_mapRepositories.Exists(pRepos->strName()))
return hzerr(E_DUPLICATE, "Repository [%s] already exists", pRepos->txtName()) ;
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ;
if (rc != E_OK)
return hzerr(rc, "Repository [%s] Register FAIL", pRepos->txtName()) ;
return rc ;
}
#if 0
hzEcode hdbADP::RegisterDataCron (hdbBinCron* pRepos)
{
if (!pRepos)
return E_ARGUMENT ;
if (!pRepos->Name())
return E_NOINIT ;
return m_mapBinDataCrons.Insert(pRepos->Name(), pRepos) ;
}
hzEcode hdbADP::RegisterDataStore (hdbBinStore* pRepos)
{
if (!pRepos)
return E_ARGUMENT ;
if (!pRepos->m_Name)
return E_NOINIT ;
return m_mapBinDataStores.Insert(pRepos->m_Name, pRepos) ;
}
#endif
hzEcode hdbADP::RegisterBinRepos (hdbBinRepos* pRepos)
{
_hzfunc("hdbADP::RegisterBinRepos") ;
if (!pRepos)
return E_ARGUMENT ;
if (!pRepos->txtName())
return E_NOINIT ;
return m_mapBinRepos.Insert(pRepos->strName(), pRepos) ;
}
bool hdbADP::IsSubClass (const hdbClass* pMain, const hdbClass* pSub)
{
// Determine if the second data class is a sub-class of the first
//
// Arguments: 1) pMain The main class
// 2) pSub The test class
//
// Returns: True If the test class is a sub-class of the main class
// False Otherwise
_hzfunc("hdbADP::IsSubClass") ;
uint32_t val_Lo ; // First item
uint32_t val_Hi ; // Last item
val_Lo = m_mapSubs.First(pMain->strType()) ;
if (val_Lo >= 0)
{
val_Hi = m_mapSubs.Last(pMain->strType()) ;
for (; val_Lo <= val_Hi ; val_Lo++)
{
if (pSub == m_mapSubs.GetObj(val_Lo))
return true ;
}
}
return false ;
}