@Override
    public Collection<String> search(String key, String value)
    {
        if (!isSearchSupported()) {
            throw new UnsupportedOperationException("None of the backing providers support this operation.");
        }

        return getGroupProviders().parallelStream()
            .filter(groupProvider -> isSearchSupported())
            .map(groupProvider -> groupProvider.search(key, value))
            .flatMap(Collection::stream)
            .collect(Collectors.toSet());
    }
Returns the names of groups that have a property matching the given key/value pair. This provides a simple
extensible search mechanism for providers with differing property sets and storage models.

The semantics of the key/value matching (wildcard support, scoping, etc.) are unspecified by the interface and
may vary for each implementation.

When a key/value combination ia provided that are not supported by a particular provider, this is ignored by that
provider (but can still be used by other providers).

Before searching or showing a search UI, use the {@link #isSearchSupported} method to ensure that searching is
supported.

@param key The name of a group property (e.g. "sharedRoster.showInRoster")
@param value The value to match for the given property
@return unmodifiable Collection of group names that match the given key/value pair.
@throws UnsupportedOperationException When none of the providers support search.
xmppserver/src/main/java/org/jivesoftware/openfire/group/GroupMultiProvider.java