docs: @Override
      public EntityIdentifier[] searchForGroups(String query, SearchMethod method, Class leaftype)
              throws GroupsException {
  
          if (isTreeRefreshRequired()) {
              refreshTree();
          }
  
          log.debug(
                  "Invoking searchForGroups():  query={}, method={}, leaftype=",
                  query,
                  method,
                  leaftype.getName());
  
          // We only match the IPerson leaf type...
          final IEntityGroup root = getRootGroup();
          if (!leaftype.equals(root.getLeafType())) {
              return new EntityIdentifier[0];
          }
  
          // We need to escape regex special characters that appear in the query string...
          final String[][] specials =
                  new String[][] {
                      /* backslash must come first! */
                      new String[] {"\\", "\\\\"},
                      new String[] {"[", "\\["},
                      /* closing ']' isn't needed b/c it's a normal character w/o a preceding '[' */
                      new String[] {"{", "\\{"},
                      /* closing '}' isn't needed b/c it's a normal character w/o a preceding '{' */
                      new String[] {"^", "\\^"},
                      new String[] {"$", "\\$"},
                      new String[] {".", "\\."},
                      new String[] {"|", "\\|"},
                      new String[] {"?", "\\?"},
                      new String[] {"*", "\\*"},
                      new String[] {"+", "\\+"},
                      new String[] {"(", "\\("},
                      new String[] {")", "\\)"}
                  };
          for (String[] s : specials) {
              query = query.replace(s[0], s[1]);
          }
  
          // Establish the regex pattern to match on...
          String regex;
          switch (method) {
              case DISCRETE:
              case DISCRETE_CI:
                  regex = query.toUpperCase();
                  break;
              case STARTS_WITH:
              case STARTS_WITH_CI:
                  regex = query.toUpperCase() + ".*";
                  break;
              case ENDS_WITH:
              case ENDS_WITH_CI:
                  regex = ".*" + query.toUpperCase();
                  break;
              case CONTAINS:
              case CONTAINS_CI:
                  regex = ".*" + query.toUpperCase() + ".*";
                  break;
              default:
                  String msg = "Unsupported search method:  " + method;
                  throw new GroupsException(msg);
          }
  
          List<EntityIdentifier> rslt = new ArrayList<>();
          for (Map.Entry<String, List<String>> y : groupsTree.getKeysByUpperCaseName().entrySet()) {
              if (y.getKey().matches(regex)) {
                  List<String> keys = y.getValue();
                  for (String k : keys) {
                      rslt.add(new EntityIdentifier(k, IEntityGroup.class));
                  }
              }
          }
  
          return rslt.toArray(new EntityIdentifier[rslt.size()]);
      }