Build Data Reference Functions

BuildDataRef builds a full data reference with instance indices from an item pointer, and provides the record id and type tag for the associated record. If the pointer is invalid it returns empty strings and 0 record id. This function is a compatible evolution of the previous BuildDR function.

GetDataRefPtr reverses the process and supplies an item pointer for a data reference, record id, and record type tag. The data reference may be relative to the record root tag, e.g. “~.NAME”, providing the record type tag is supplied. If the record type tag is omitted, it is extracted from the full data reference. If any parameters are invalid it returns a NULL pointer.

Requires: None


@function:	BuildDataRef
@description:	Get Full Data Reference for Pointer
@parameters:	Item Pointer
@returns:	Data Reference String, Record Id Integer, Record Type Tag String
@requires:	None

function BuildDataRef(ptrRef)

	local strDataRef = ""		-- Data Reference with instance indices e.g. INDI.RESI[2].ADDR
	local intRecId   = 0		-- Record Id for associated Record
	local strRecTag  = ""		-- Record Tag of associated Record type i.e. INDI, FAM, NOTE, SOUR, etc

	-- getDataRef() is called recursively per level of the Data Ref
	-- ptrRef points to the upper Data Ref levels yet to be analysed
	-- strRef compiles the lower Data Ref levels including instances

	local function getDataRef(ptrRef,strRef)
		local ptrTag = ptrRef:Clone()
		local strTag = fhGetTag(ptrTag)			-- Current level Tag
		if ptrTag:IsNotNull() then			-- Parent level exists
			local intSib = 1
			local ptrSib = ptrRef:Clone()		-- Pointer to siblings with same Tag
			while ptrSib:IsNotNull() do		-- Count previous siblings with same Tag
				intSib = intSib + 1
			if intSib > 1 then 	strTag = strTag.."["..intSib.."]" end
			getDataRef(ptrTag,"."..strTag..strRef)	-- Now analyse the parent level
			strDataRef = strTag..strRef		-- Record level reached, so set return values
			intRecId   = fhGetRecordId(ptrRef)
			strRecTag  = strTag
			if not fhIsValidDataRef(strDataRef) then print(strDataRef.." is Invalid") end
	end -- local function getDataRef

	if type(ptrRef) == "userdata" then getDataRef(ptrRef,"") end

	return strDataRef, intRecId, strRecTag

end -- function BuildDataRef

@function:	GetDataRefPtr
@description:	Get Pointer for Full Data Reference
@parameters:	Data Reference String, Record Id Integer, Record Type Tag String (optional)
@returns:	Item Pointer which IsNull() if any parameters are invalid
@requires:	None

function GetDataRefPtr(strDataRef,intRecId,strRecTag)
	strDataRef = strDataRef or ""
	if not strRecTag then
		strRecTag = strDataRef:gsub("^(%u+).*$","%1")	-- Extract Record Tag from Data Ref
	local ptrRef = fhNewItemPtr()
	ptrRef:MoveToRecordById(strRecTag,intRecId or 0)	-- Lookup the Record by Id
	ptrRef:MoveTo(ptrRef,strDataRef)			-- Move to the Data Ref
	return ptrRef
end -- function GetDataRefPtr



local ptrRef = fhNewItemPtr()
print( BuildDataRef(ptrRef) )		-->>	FAM.MARR	1	FAM

ptrRef = GetDataRefPtr("~.NAME",2,"INDI")
print(fhGetDisplayText(ptrRef))		-->>	Name: Julia Amanda FISH

ptrRef = GetDataRefPtr("INDI.NAME",2)
print(fhGetDisplayText(ptrRef))		-->>	Name: Julia Amanda FISH

while ptrRef:IsNotNull() do
	local strRef, intId, strTag = BuildDataRef(ptrRef)
	print(strRef, intId, strTag)	-->>	INDI.NAME	1	INDI
	ptrRef = GetDataRefPtr(strRef,intId)
	print(fhGetDisplayText(ptrRef))	-->>	Name: Anthony Edward MUNRO
	if intId > 1000 then break end


Previous Code

@function: BuildDR
@description: Get Data Reference for Tag
@parameters: Item Pointer
@returns: Data reference String (excluding index)
@requires: none
function BuildDR(ptr)
   local ptrTemp = fhNewItemPtr()
   strDR = fhGetTag(ptrTemp)
   while fhHasParentItem(ptrTemp) do
      strDR = fhGetTag(ptrTemp)..'.'..strDR
   return strDR


Last update: 16 Dec 2020