class GroupList extends LinkedList<String> {
        private static final long serialVersionUID = 1L;
        public GroupList(MatchResult matchResult) {
            for (int i = 0; i <= matchResult.groupCount(); i++) {
                add(matchResult.group(i));
            }
        }
    };
    
    @Override
    public void extract(CrawlURI curi) {<FILL_FUNCTION_BODY>

        // { regex name -> list of matches }
        Map<String, MatchList> matchLists;

        // uri regex
        Matcher matcher = TextUtils.getMatcher(getUriRegex(), curi.getURI());
        if (matcher.matches()) {
            matchLists = new LinkedHashMap<String,MatchList>();
            matchLists.put("uriRegex", new MatchList(new GroupList(matcher)));
        } else {
	    TextUtils.recycleMatcher(matcher);
            return; // if uri regex doesn't match, we're done
        }
        
        ReplayCharSequence cs;
        try {
            cs = curi.getRecorder().getContentReplayCharSequence();
        } catch (IOException e) {
            curi.getNonFatalFailures().add(e);
            LOGGER.log(Level.WARNING, "Failed get of replay char sequence in "
                    + Thread.currentThread().getName(), e);
	    TextUtils.recycleMatcher(matcher);
            return;
        }
        
        // run all the regexes on the content and cache results
        for (String regexName: getContentRegexes().keySet()) {
            String regex = getContentRegexes().get(regexName);
            MatchList matchList = new MatchList(regex, cs);
            if (matchList.isEmpty()) {
		TextUtils.recycleMatcher(matcher);
                return; // no match found for regex, so we can stop now
            }
            matchLists.put(regexName, matchList);
        }

        /*
         * If we have 3 regexes, the first one has 1 match, second has 12
         * matches, third has 3 matches, then we have 36 combinations of
         * matches, thus 36 outlinks to extracted.
         */
        int numOutlinks = 1;
        for (MatchList matchList: matchLists.values()) {
            numOutlinks *= matchList.size();
        }
        
        String[] regexNames = matchLists.keySet().toArray(new String[0]);
        for (int i = 0; i < numOutlinks; i++) {
            Map<String, Object> bindings = makeBindings(matchLists, regexNames, i);
            buildAndAddOutlink(curi, bindings);
        }
	TextUtils.recycleMatcher(matcher);
    
<methods>public non-sealed void <init>() ,public static void add(org.archive.modules.CrawlURI, int, java.lang.String, org.archive.modules.extractor.LinkContext, org.archive.modules.extractor.Hop) throws URIException,public static org.archive.modules.CrawlURI addRelativeToBase(org.archive.modules.CrawlURI, int, java.lang.CharSequence, org.archive.modules.extractor.LinkContext, org.archive.modules.extractor.Hop) throws URIException,public static org.archive.modules.CrawlURI addRelativeToVia(org.archive.modules.CrawlURI, int, java.lang.String, org.archive.modules.extractor.LinkContext, org.archive.modules.extractor.Hop) throws URIException,public org.archive.modules.extractor.ExtractorParameters getExtractorParameters() ,public org.archive.modules.extractor.UriErrorLoggerModule getLoggerModule() ,public void logUriError(URIException, org.archive.net.UURI, java.lang.CharSequence) ,public java.lang.String report() ,public void setExtractorParameters(org.archive.modules.extractor.ExtractorParameters) ,public void setLoggerModule(org.archive.modules.extractor.UriErrorLoggerModule) <variables>public static final org.archive.modules.extractor.ExtractorParameters DEFAULT_PARAMETERS,private static final java.util.logging.Logger LOGGER,protected transient org.archive.modules.extractor.ExtractorParameters extractorParameters,private static final java.util.logging.Logger logger,protected transient org.archive.modules.extractor.UriErrorLoggerModule loggerModule,protected java.util.concurrent.atomic.AtomicLong numberOfLinksExtracted