default boolean forEachColumn(FacesContext context, UIComponent root, boolean unwrapDynamicColumns, boolean skipUnrendered, boolean skipColumnGroups,
            Predicate<UIColumn> callback) {
        for (int i = 0; i < root.getChildCount(); i++) {
            UIComponent child = root.getChildren().get(i);
            if (!(child instanceof Columns) && skipUnrendered && !child.isRendered()) {
                continue;
            }

            if (child instanceof Columns) {
                Columns columns = (Columns) child;
                if (unwrapDynamicColumns) {
                    for (int j = 0; j < columns.getRowCount(); j++) {
                        DynamicColumn dynaColumn = new DynamicColumn(j, columns, context);
                        dynaColumn.applyStatelessModel();

                        if (skipUnrendered && !dynaColumn.isRendered()) {
                            continue;
                        }

                        if (!callback.test(dynaColumn)) {
                            return false;
                        }
                    }
                }
                else {
                    if (!callback.test(columns)) {
                        return false;
                    }
                }
            }
            else if (child instanceof Column) {
                Column column = (Column) child;
                if (!callback.test(column)) {
                    return false;
                }
            }
            else if (child instanceof ColumnGroup && !skipColumnGroups) {
                // columnGroup must contain p:row(s) as child
                for (int j = 0; j < child.getChildCount(); j++) {
                    UIComponent row = child.getChildren().get(j);
                    if (skipUnrendered && !row.isRendered()) {
                        continue;
                    }

                    if (!forEachColumn(context, row, unwrapDynamicColumns, skipUnrendered, skipColumnGroups, callback)) {
                        return false;
                    }
                }
            }
            else if (child instanceof ColumnAware) {
                ColumnAware columnAware = (ColumnAware) child;
                for (int j = 0; j < ((UIComponent) columnAware).getChildCount(); j++) {
                    UIComponent columnAwareChild = ((UIComponent) columnAware).getChildren().get(j);
                    if (skipUnrendered && !columnAwareChild.isRendered()) {
                        continue;
                    }

                    if (!forEachColumn(context, columnAwareChild, unwrapDynamicColumns, skipUnrendered, skipColumnGroups, callback)) {
                        return false;
                    }
                }
            }
            else if (ComponentUtils.isUIRepeat(child)) {
                VisitContext visitContext = VisitContext.createVisitContext(context, null,
                        ComponentUtils.VISIT_HINTS_SKIP_UNRENDERED);
                child.visitTree(visitContext, (ctx, target) -> {
                    if (ComponentUtils.isUIRepeat(target)) {
                        return VisitResult.ACCEPT;
                    }

                    // for now just support basic p:column in ui:repeat
                    if (target instanceof Column) {
                        Column column = (Column) target;
                        if (!callback.test(column)) {
                            return VisitResult.COMPLETE;
                        }
                    }

                    return VisitResult.REJECT;
                });
            }
        }

        return true;
    }
NOTE: this is for internal usage only!

@param context the {@link FacesContext}
@param root the {@link UIComponent} where the search starts from
@param unwrapDynamicColumns if the callback should be called for each item of p:columns with {@link DynamicColumn},
                             or just once with {@link Columns}
@param skipUnrendered If unrendered components should be skipped
@param skipColumnGroups If {@link ColumnGroup} components should be skipped
@param callback The callback, which will be invoked for each column. If it returns false, the algorithm will be cancelled
@return false when the algorithm was cancelled
primefaces/src/main/java/org/primefaces/component/api/ColumnAware.java