001// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
002//
003// SPDX-License-Identifier: Apache-2.0
004
005package org.pgpainless.util.selection.userid;
006
007import java.util.ArrayList;
008import java.util.List;
009
010import org.bouncycastle.openpgp.PGPKeyRing;
011import org.pgpainless.PGPainless;
012
013import javax.annotation.Nonnull;
014
015public abstract class SelectUserId {
016
017    protected abstract boolean accept(String userId);
018
019    public List<String> selectUserIds(PGPKeyRing keyRing) {
020        List<String> userIds = PGPainless.inspectKeyRing(keyRing).getValidUserIds();
021        return selectUserIds(userIds);
022    }
023
024    public List<String> selectUserIds(List<String> userIds) {
025        List<String> selected = new ArrayList<>();
026        for (String userId : userIds) {
027            if (accept(userId)) {
028                selected.add(userId);
029            }
030        }
031        return selected;
032    }
033
034    public String firstMatch(PGPKeyRing keyRing) {
035        return firstMatch(selectUserIds(keyRing));
036    }
037
038    public String firstMatch(List<String> userIds) {
039        for (String userId : userIds) {
040            if (accept(userId)) {
041                return userId;
042            }
043        }
044        return null;
045    }
046
047    public static SelectUserId containsSubstring(@Nonnull CharSequence query) {
048        return new SelectUserId() {
049            @Override
050            protected boolean accept(String userId) {
051                return userId.contains(query.toString());
052            }
053        };
054    }
055
056    public static SelectUserId exactMatch(@Nonnull CharSequence query) {
057        return new SelectUserId() {
058            @Override
059            protected boolean accept(String userId) {
060                return userId.equals(query.toString());
061            }
062        };
063    }
064
065    public static SelectUserId startsWith(@Nonnull CharSequence substring) {
066        String string = substring.toString();
067        return new SelectUserId() {
068            @Override
069            protected boolean accept(String userId) {
070                return userId.startsWith(string);
071            }
072        };
073    }
074
075    public static SelectUserId containsEmailAddress(@Nonnull CharSequence email) {
076        String string = email.toString();
077        return containsSubstring(string.matches("^<.+>$") ? string : '<' + string + '>');
078    }
079
080    public static SelectUserId validUserId(PGPKeyRing keyRing) {
081        return new SelectUserId() {
082            @Override
083            protected boolean accept(String userId) {
084                return PGPainless.inspectKeyRing(keyRing).isUserIdValid(userId);
085            }
086        };
087    }
088
089    public static SelectUserId and(SelectUserId... strategies) {
090        return new SelectUserId() {
091            @Override
092            protected boolean accept(String userId) {
093                boolean accept = true;
094                for (SelectUserId strategy : strategies) {
095                    accept &= strategy.accept(userId);
096                }
097                return accept;
098            }
099        };
100    }
101
102    public static SelectUserId or(SelectUserId... strategies) {
103        return new SelectUserId() {
104            @Override
105            protected boolean accept(String userId) {
106                boolean accept = false;
107                for (SelectUserId strategy : strategies) {
108                    accept |= strategy.accept(userId);
109                }
110                return accept;
111            }
112        };
113    }
114
115    public static SelectUserId not(SelectUserId strategy) {
116        return new SelectUserId() {
117            @Override
118            protected boolean accept(String userId) {
119                return !strategy.accept(userId);
120            }
121        };
122    }
123
124    public static SelectUserId byEmail(CharSequence email) {
125        return SelectUserId.or(
126                SelectUserId.exactMatch(email),
127                SelectUserId.containsEmailAddress(email)
128        );
129    }
130}