docs: public static String resolveClientIds(FacesContext context, UIComponent source, String expressions, int hints) {
  
          if (LangUtils.isValueBlank(expressions)) {
              if (SearchExpressionUtils.isHintSet(hints, SearchExpressionHint.PARENT_FALLBACK)) {
                  return source.getParent().getClientId(context);
              }
  
              return null;
          }
  
          String[] splittedExpressions = splitExpressions(context, source, expressions);
  
          if (splittedExpressions != null && splittedExpressions.length > 0) {
  
              final char separatorChar = UINamingContainer.getSeparatorChar(context);
  
              StringBuilder expressionsBuffer = SharedStringBuilder.get(context, SHARED_EXPRESSION_BUFFER_KEY);
  
              for (int i = 0; i < splittedExpressions.length; i++) {
                  String expression = splittedExpressions[i].trim();
  
                  if (LangUtils.isValueBlank(expression)) {
                      continue;
                  }
  
                  validateExpression(context, source, expression, separatorChar);
  
                  if (isPassTroughExpression(expression)) {
                      if (expressionsBuffer.length() > 0) {
                          expressionsBuffer.append(" ");
                      }
                      expressionsBuffer.append(expression);
                  }
                  else {
                      // if it contains a keyword and it's not a nested expression (e.g. @parent:@parent), we don't need to loop
                      if (expression.contains(SearchExpressionConstants.KEYWORD_PREFIX) && expression.indexOf(separatorChar) != -1) {
                          String clientIds = resolveClientIdsByExpressionChain(context, source, expression, separatorChar, hints);
                          if (!LangUtils.isValueBlank(clientIds)) {
                              if (expressionsBuffer.length() > 0) {
                                  expressionsBuffer.append(" ");
                              }
                              expressionsBuffer.append(clientIds);
                          }
                      }
                      else {
                          // it's a keyword and not nested, just ask our resolvers
                          if (expression.contains(SearchExpressionConstants.KEYWORD_PREFIX)) {
                              SearchExpressionResolver resolver = SearchExpressionResolverFactory.findResolver(expression);
  
                              if (resolver instanceof ClientIdSearchExpressionResolver) {
                                  String clientIds = ((ClientIdSearchExpressionResolver) resolver).resolveClientIds(context, source, source, expression, hints);
                                  if (!LangUtils.isValueBlank(clientIds)) {
                                      if (expressionsBuffer.length() > 0) {
                                          expressionsBuffer.append(" ");
                                      }
                                      expressionsBuffer.append(clientIds);
                                  }
                              }
                              else if (resolver instanceof MultiSearchExpressionResolver) {
                                  ArrayList<UIComponent> result = new ArrayList<>();
                                  ((MultiSearchExpressionResolver) resolver).resolveComponents(context, source, source, expression, result, hints);
                                  for (int j = 0; j < result.size(); j++) {
                                      UIComponent component = result.get(j);
                                      validateRenderer(context, source, component, expression, hints);
                                      if (expressionsBuffer.length() > 0) {
                                          expressionsBuffer.append(" ");
                                      }
                                      expressionsBuffer.append(component.getClientId());
                                  }
                              }
                              else {
                                  UIComponent component = resolver.resolveComponent(context, source, source, expression, hints);
  
                                  if (component == null) {
                                      if (!SearchExpressionUtils.isHintSet(hints, SearchExpressionHint.IGNORE_NO_RESULT)) {
                                          cannotFindComponent(context, source, expression);
                                      }
                                  }
                                  else {
                                      validateRenderer(context, source, component, expression, hints);
                                      if (expressionsBuffer.length() > 0) {
                                          expressionsBuffer.append(" ");
                                      }
                                      expressionsBuffer.append(component.getClientId(context));
                                  }
                              }
                          }
                          // default ID case
                          else {
                              ResolveClientIdCallback callback = new ResolveClientIdCallback(source, hints, expression);
                              resolveComponentById(source, expression, separatorChar, context, callback);
  
                              if (callback.getClientId() == null && !SearchExpressionUtils.isHintSet(hints, SearchExpressionHint.IGNORE_NO_RESULT)) {
                                  cannotFindComponent(context, source, expression);
                              }
  
                              if (callback.getClientId() != null) {
                                  if (expressionsBuffer.length() > 0) {
                                      expressionsBuffer.append(" ");
                                  }
                                  expressionsBuffer.append(callback.getClientId());
                              }
                          }
                      }
                  }
              }
  
              String clientIds = expressionsBuffer.toString();
              if (!LangUtils.isValueBlank(clientIds)) {
                  return clientIds;
              }
          }
  
          return null;
      }