class MatchesListRegexDecideRule extends PredicatedDecideRule {
    private static final long serialVersionUID = 3L;
    private static final Logger logger =
            Logger.getLogger(MatchesListRegexDecideRule.class.getName());

    {
        setTimeoutPerRegexSeconds(0L);
    }
    public long getTimeoutPerRegexSeconds() { return (Long) kp.get("timeout");}
    /**
     * The timeout for regular expression matching, in seconds. If set to 0 or negative then no timeout is specified and
     * there is no upper limit to how long the matching may take. See the corresponding test class MatchesListRegexDecideRuleTest
     * for a pathological example.
     */
    public void setTimeoutPerRegexSeconds(long timeoutPerRegexSeconds) { kp.put("timeout", timeoutPerRegexSeconds);}


    {
        setRegexList(new ArrayList<Pattern>());
    }
    @SuppressWarnings("unchecked")
    public List<Pattern> getRegexList() {
        return (List<Pattern>) kp.get("regexList");
    }
    /**
     * The list of regular expressions to evalute against the URI.
     */
    public void setRegexList(List<Pattern> patterns) {
        kp.put("regexList", patterns);
    }

    {
        setListLogicalOr(true);
    }
    public boolean getListLogicalOr() {
        return (Boolean) kp.get("listLogicalOr");
    }
    /**
     * True if the list of regular expression should be considered as logically
     * AND when matching. False if the list of regular expressions should be
     * considered as logically OR when matching.
     */
    public void setListLogicalOr(boolean listLogicalOr) {
        kp.put("listLogicalOr",listLogicalOr);
    }

    /**
     * Usual constructor. 
     */
    public MatchesListRegexDecideRule() {
    }

    /**
     * Evaluate whether given object's string version
     * matches configured regexes
     */
    @Override
    protected boolean evaluate(CrawlURI uri) {<FILL_FUNCTION_BODY>}

}

        List<Pattern> regexes = getRegexList();
        if(regexes.size()==0){
            return false;
        }

        String str = uri.toString();
        boolean listLogicOR = getListLogicalOr();

        for (Pattern p: regexes) {
            boolean matches = false;
            if (getTimeoutPerRegexSeconds() <= 0) {
                matches = p.matcher(str).matches();
            } else {
                InterruptibleCharSequence interruptible = new InterruptibleCharSequence(str);
                FutureTask<Boolean> matchesFuture = new FutureTask<>(() -> p.matcher(interruptible).matches());
                ForkJoinPool.commonPool().submit(matchesFuture);
                try {
                    matches = matchesFuture.get(getTimeoutPerRegexSeconds(), TimeUnit.SECONDS);
                } catch (TimeoutException e) {
                    matchesFuture.cancel(true);
                    logger.warning("Timed out after " + getTimeoutPerRegexSeconds() + " seconds waiting for '" + p + "' to match.");
                } catch (InterruptedException e) {
                    matchesFuture.cancel(true);
                    logger.warning("InterruptedException while waiting for '" + p + "' to match.");
                } catch (ExecutionException e) {
                    matchesFuture.cancel(true);
                    logger.warning("ExecutionException while waiting for '" + p + "' to match: " + e.getMessage());
                }
            }

            if (logger.isLoggable(Level.FINER)) {
                logger.finer("Tested '" + str + "' match with regex '" +
                        p.pattern() + " and result was " + matches);
            }

            if(matches){
                if(listLogicOR){
                    // OR based and we just got a match, done!
                    logger.fine("Matched: " + str);
                    return true;
                }
            } else {
                if(listLogicOR == false){
                    // AND based and we just found a non-match, done!
                    return false;
                }
            }
        }

        if (listLogicOR) {
            return false;
        } else {
            return true;
        }
    
<methods>public void <init>() ,public org.archive.modules.deciderules.DecideResult getDecision() ,public org.archive.modules.deciderules.DecideResult onlyDecision(org.archive.modules.CrawlURI) ,public void setDecision(org.archive.modules.deciderules.DecideResult) <variables>private static final long serialVersionUID