fnTraverseColumnRelations = function(mColumns, aNewRelations) {
				let oColumn;
				let i;
				let aDirectRelations = [];
				aNewRelations = aNewRelations || [];

				// get the direct relations for all collected columns
				// columns have a logical relation with each other, if they are spanned by other column headers or
				// of they by itself are spanning other columns. Since those columns are logically tightly coupled,
				// they can be seen as an immutable block of columns.
				for (i = 0; i < aNewRelations.length; i++) {
					oColumn = mColumns[aNewRelations[i]];
					aDirectRelations = aDirectRelations.concat(ColumnUtils.getParentSpannedColumns(oTable, oColumn.getId()));
					aDirectRelations = aDirectRelations.concat(ColumnUtils._getChildrenSpannedColumns(oTable, oColumn.getId()));
				}

				aNewRelations = [];
				for (i = 0; i < aDirectRelations.length; i++) {
					oColumn = aDirectRelations[i].column;
					const sColumnId = oColumn.getId();
					if (!mColumns[sColumnId]) {
						// keep track about new found relations for later recursion to avoid collecting information about
						// already known related columns again.
						aNewRelations.push(sColumnId);
						mColumns[sColumnId] = oColumn;
					}
				}

				if (aNewRelations.length > 0) {
					// if new relations where found, another round of recursion is required to get the related columns
					// of the new relations. Afterwards merge the result with the already known related columns
					return fnTraverseColumnRelations(mColumns, aNewRelations);
				} else {
					return mColumns;
				}
			}
Returns a map of the column boundaries for the column identified by <code>sColumnId</code>.
This function considers all overlapping spans of columns to determine the start and end indices.

@param {sap.ui.table.Table} oTable Instance of the table.
@param {string} sColumnId ID of the column.
@returns {{startColumn: sap.ui.table.Column, startIndex: int, endColumn: sap.ui.table.Column, endIndex: int}|undefined}
Map of column boundaries.
@private