docs: @Override
      public List<IPersonAttributes> searchForPeople(
              final IPerson searcher, final Map<String, Object> query) {
  
          // get the IAuthorizationPrincipal for the searching user
          final IAuthorizationPrincipal principal = getPrincipalForUser(searcher);
  
          // build a set of all possible user attributes the current user has
          // permission to view
          final Set<String> permittedAttributes = getPermittedAttributes(principal);
  
          // remove any query attributes that the user does not have permission
          // to view
          final Map<String, Object> inUseQuery = new HashMap<>();
          for (Map.Entry<String, Object> queryEntry : query.entrySet()) {
              final String attr = queryEntry.getKey();
              if (permittedAttributes.contains(attr)) {
                  inUseQuery.put(attr, queryEntry.getValue());
              } else {
                  this.logger.warn(
                          "User '"
                                  + searcher.getName()
                                  + "' attempted searching on attribute '"
                                  + attr
                                  + "' which is not allowed in the current configuration. The attribute will be ignored.");
              }
          }
  
          // ensure the query has at least one search attribute defined
          if (inUseQuery.keySet().size() == 0) {
              throw new IllegalArgumentException("Search query is empty");
          }
  
          // get the set of people matching the search query
          final Set<IPersonAttributes> people = this.personAttributeDao.getPeople(inUseQuery);
          if (people == null) {
              return Collections.emptyList();
          }
  
          // To improve efficiency and not do as many permission checks or person directory searches,
          // if we have too many results and all people in the returned set of personAttributes have
          // a displayName, pre-sort the set and limit it to maxResults. The typical use case is that
          // LDAP returns results that have the displayName populated.  Note that a disadvantage of
          // this
          // approach is that the smaller result set may have entries that permissions prevent the
          // current users from viewing the person and thus reduce the number of final results, but
          // that is rare (typical use case is users can't view administrative internal accounts or
          // the
          // system account, none of which tend to be in LDAP).  We could retain a few more than
          // maxResults
          // to offset that chance, but IMHO not worth the cost of extra external queries.
  
          List<IPersonAttributes> peopleList = new ArrayList<>(people);
          if (peopleList.size() > maxResults && allListItemsHaveDisplayName(peopleList)) {
              logger.debug(
                      "All items contained displayName; pre-sorting list of size {} and truncating to {}",
                      peopleList.size(),
                      maxResults);
              // sort the list by display name
              Collections.sort(peopleList, new DisplayNameComparator());
              peopleList = peopleList.subList(0, maxResults);
          }
          // Construct a new representation of the persons limited to attributes the searcher
          // has permissions to view.  Will change order of the list.
          List<IPersonAttributes> list =
                  getVisiblePersons(principal, permittedAttributes, peopleList);
  
          // Sort the list by display name
          Collections.sort(list, new DisplayNameComparator());
  
          // limit the list to a maximum number of returned results
          if (list.size() > maxResults) {
              list = list.subList(0, maxResults);
          }
  
          return list;
      }