Build Data Reference Functions (code snippet)

Description

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

Code

--[[
@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
		ptrTag:MoveToParentItem(ptrTag)
		if ptrTag:IsNotNull() then			-- Parent level exists
			local intSib = 1
			local ptrSib = ptrRef:Clone()		-- Pointer to siblings with same Tag
			ptrSib:MovePrev("SAME_TAG")
			while ptrSib:IsNotNull() do		-- Count previous siblings with same Tag
				intSib = intSib + 1
				ptrSib:MovePrev("SAME_TAG")
			end
			if intSib > 1 then 	strTag = strTag.."["..intSib.."]" end
			getDataRef(ptrTag,"."..strTag..strRef)	-- Now analyse the parent level
		else
			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
	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
	end
	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

Usage

local ptrRef = fhNewItemPtr()
ptrRef:MoveToFirstRecord("FAM")
ptrRef:MoveToFirstChildItem(ptrRef)
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
 
ptrRef:MoveToFirstRecord("INDI")
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
	ptrRef:MoveNextSpecial()
	if intId > 1000 then break end
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()
   ptrTemp:MoveTo(ptr)
   strDR = fhGetTag(ptrTemp)
   while fhHasParentItem(ptrTemp) do
      ptrTemp:MoveToParentItem(ptrTemp)
      strDR = fhGetTag(ptrTemp)..'.'..strDR
   end
   return strDR
end