// SPDX-FileCopyrightText: 2021 Paul Schaub // // SPDX-License-Identifier: Apache-2.0 package org.pgpainless.util.selection.userid; import java.util.ArrayList; import java.util.List; import org.bouncycastle.openpgp.PGPKeyRing; import org.pgpainless.PGPainless; import org.pgpainless.key.info.KeyRingInfo; import javax.annotation.Nonnull; import javax.annotation.Nullable; /** * Filter for selecting user-ids from keys and from lists. */ public abstract class SelectUserId { /** * Return true, if the given user-id is accepted by this particular filter, false otherwise. * * @param userId user-id * @return acceptance of the filter */ protected abstract boolean accept(String userId); /** * Select all currently valid user-ids of the given key ring. * * @param keyRing public or secret key ring * @return valid user-ids */ @Nonnull public List selectUserIds(@Nonnull PGPKeyRing keyRing) { List userIds = PGPainless.inspectKeyRing(keyRing).getValidUserIds(); return selectUserIds(userIds); } /** * Select all acceptable (see {@link #accept(String)}) from the given list of user-ids. * * @param userIds list of user-ids * @return sub-list of acceptable user-ids */ @Nonnull public List selectUserIds(@Nonnull List userIds) { List selected = new ArrayList<>(); for (String userId : userIds) { if (accept(userId)) { selected.add(userId); } } return selected; } /** * Return the first valid, acceptable user-id from the given public or secret key ring. * * @param keyRing public or secret key ring * @return first matching valid user-id or null */ @Nullable public String firstMatch(PGPKeyRing keyRing) { return firstMatch(selectUserIds(keyRing)); } /** * Return the first valid, acceptable user-id from the list of user-ids. * * @param userIds list of user-ids * @return first matching valid user-id or null */ @Nullable public String firstMatch(@Nonnull List userIds) { for (String userId : userIds) { if (accept(userId)) { return userId; } } return null; } /** * Filter that filters for user-ids which contain the given
query
as a substring. * * @param query query * @return filter */ public static SelectUserId containsSubstring(@Nonnull CharSequence query) { return new SelectUserId() { @Override protected boolean accept(String userId) { return userId.contains(query.toString()); } }; } /** * Filter that filters for user-ids which match the given
query
exactly. * * @param query query * @return filter */ public static SelectUserId exactMatch(@Nonnull CharSequence query) { return new SelectUserId() { @Override protected boolean accept(String userId) { return userId.equals(query.toString()); } }; } /** * Filter that filters for user-ids which start with the given
substring
. * * @param substring substring * @return filter */ public static SelectUserId startsWith(@Nonnull CharSequence substring) { String string = substring.toString(); return new SelectUserId() { @Override protected boolean accept(String userId) { return userId.startsWith(string); } }; } /** * Filter that filters for user-ids which contain the given
email
address. * Note: This only accepts user-ids which properly have the email address surrounded by angle brackets. * * The argument
email
can both be a plain email address (
"foo@bar.baz"
), * or surrounded by angle brackets ({@code
""
}), the result of the filter will be the same. * * @param email email address * @return filter */ public static SelectUserId containsEmailAddress(@Nonnull CharSequence email) { String string = email.toString(); return containsSubstring(string.matches("^<.+>$") ? string : '<' + string + '>'); } /** * Filter that filters for valid user-ids on the given
keyRing
only. * * @param keyRing public / secret keys * @return filter */ public static SelectUserId validUserId(PGPKeyRing keyRing) { final KeyRingInfo info = PGPainless.inspectKeyRing(keyRing); return new SelectUserId() { @Override protected boolean accept(String userId) { return info.isUserIdValid(userId); } }; } /** * Filter that filters for user-ids which pass all the given
filters
. * * @param filters filters * @return filter */ public static SelectUserId and(SelectUserId... filters) { return new SelectUserId() { @Override protected boolean accept(String userId) { boolean accept = true; for (SelectUserId filter : filters) { accept &= filter.accept(userId); } return accept; } }; } /** * Filter that filters for user-ids which pass at least one of the given
filters
. * * @param filters filters * @return filter */ public static SelectUserId or(SelectUserId... filters) { return new SelectUserId() { @Override protected boolean accept(String userId) { boolean accept = false; for (SelectUserId filter : filters) { accept |= filter.accept(userId); } return accept; } }; } /** * Filter that inverts the result of the given
filter
. * * @param filter filter * @return inverting filter */ public static SelectUserId not(SelectUserId filter) { return new SelectUserId() { @Override protected boolean accept(String userId) { return !filter.accept(userId); } }; } /** * Filter that selects user-ids by the given
email
address. * It returns user-ids which either contain the given
email
address as angle-bracketed string, * or which equal the given
email
string exactly. * * @param email email * @return filter */ public static SelectUserId byEmail(CharSequence email) { return SelectUserId.or( SelectUserId.exactMatch(email), SelectUserId.containsEmailAddress(email) ); } }