@Override
	public ProgramLocation getProgramLocation(int modelRow, int modelColumn) {
		if (modelRow < 0 || modelRow >= filteredData.size()) {
			return null;
		}

		ROW_TYPE rowObject = filteredData.get(modelRow);
		DynamicTableColumn<ROW_TYPE, ?, ?> tableColumn = getColumn(modelColumn);
		if (tableColumn instanceof ProgramLocationTableColumn<?, ?>) {

			@SuppressWarnings("unchecked") // we checked			
			ProgramLocationTableColumn<ROW_TYPE, ?> programField =
				(ProgramLocationTableColumn<ROW_TYPE, ?>) tableColumn;
			ProgramLocation loc = programField.getProgramLocation(rowObject,
				getColumnSettings(modelColumn), getProgram(), serviceProvider);
			if (loc != null) {
				return loc;
			}
		}

		Address address = getAddress(modelRow, modelColumn);
		if (address != null) {
			return new ProgramLocation(getProgram(), address);
		}

		return null;
	}
If the given column supports row mapping, then use that column to get the mapped row.  In 
this case, our table may have a row object, like Function, that the column maps to another
type that it needs, like Address.

@param tableColumn the table column
@param currentRowObject the table's actual non-mapped row value
@param columnIndex the column index
@return the mapped row value or null
Ghidra/Features/Base/src/main/java/ghidra/util/table/GhidraProgramTableModel.java