All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hudson.plugins.tasks.parser.TaskScanner Maven / Gradle / Ivy

Go to download

This plug-in scans the workspace files for open tasks and generates a trend report.

There is a newer version: 4.36-h-1
Show newest version
package hudson.plugins.tasks.parser;


import hudson.AbortException;
import hudson.plugins.analysis.util.model.Priority;
import hudson.plugins.tasks.Messages;

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.LineIterator;
import org.apache.commons.lang.StringUtils;

/**
 * Scans a given input stream for open tasks.
 *
 * @author Ulli Hafner
 */
public class TaskScanner {
    private static final String WORD_BOUNDARY = "\\b";

    /** The regular expression patterns to be used to scan the files. One pattern per priority. */
    private final Map patterns = new HashMap();

    private boolean isInvalidPattern;
    private final StringBuilder errorMessage = new StringBuilder();

    /**
     * Creates a new instance of {@link TaskScanner}.
     */
    public TaskScanner() {
        this("FIXME", "TODO", "@deprecated", false);
    }

    /**
     * Creates a new instance of {@link TaskScanner}.
     *
     * @param high
     *            tag identifiers indicating high priority
     * @param normal
     *            tag identifiers indicating normal priority
     * @param low
     *            tag identifiers indicating low priority
     * @param ignoreCase
     *            if case should be ignored during matching
     */
    public TaskScanner(final String high, final String normal, final String low, final boolean ignoreCase) {
        if (StringUtils.isNotBlank(high)) {
            patterns.put(Priority.HIGH, compile(high, ignoreCase));
        }
        if (StringUtils.isNotBlank(normal)) {
            patterns.put(Priority.NORMAL, compile(normal, ignoreCase));
        }
        if (StringUtils.isNotBlank(low)) {
            patterns.put(Priority.LOW, compile(low, ignoreCase));
        }
    }

    /**
     * Compiles a regular expression pattern to scan for tag identifiers.
     *
     * @param tagIdentifiers
     *            the identifiers to scan for
     * @param ignoreCase
     *            specifies if case should be ignored
     * @return the compiled pattern
     */
    private Pattern compile(final String tagIdentifiers, final boolean ignoreCase) {
        try {
            String[] tags;
            if (tagIdentifiers.indexOf(',') == -1) {
                tags = new String[] {tagIdentifiers};
            }
            else {
                tags = StringUtils.split(tagIdentifiers, ",");
            }
            List regexps = new ArrayList();
            for (int i = 0; i < tags.length; i++) {
                String tag = tags[i].trim();
                if (StringUtils.isNotBlank(tag)) {
                    StringBuilder actual = new StringBuilder();
                    if (Character.isLetterOrDigit(tag.charAt(0))) {
                        actual.append(WORD_BOUNDARY);
                    }
                    actual.append(tag);
                    if (Character.isLetterOrDigit(tag.charAt(tag.length() - 1))) {
                        actual.append(WORD_BOUNDARY);
                    }
                    regexps.add(actual.toString());
                }
            }
            int flags;
            if (ignoreCase) {
                flags = Pattern.CASE_INSENSITIVE;
            }
            else {
                flags = 0;
            }
            return Pattern.compile("^.*(" + StringUtils.join(regexps.iterator(), "|") + ")(.*)$", flags);
        }
        catch (PatternSyntaxException exception) {
            isInvalidPattern = true;
            errorMessage.append(Messages.Tasks_PatternError(tagIdentifiers, exception.getMessage()));
            errorMessage.append("\n");

            return null;
        }
    }

    /**
     * Scans the specified input stream for open tasks.
     *
     * @param reader
     *            the file to scan
     * @return the result stored as java project
     * @throws IOException
     *             if we can't read the file
     */
    public Collection scan(final Reader reader) throws IOException {
        try {
            if (isInvalidPattern) {
                throw new AbortException(errorMessage.toString());
            }
            LineIterator lineIterator = IOUtils.lineIterator(reader);
            List tasks = new ArrayList();
            for (int lineNumber = 1; lineIterator.hasNext(); lineNumber++) {
                String line = (String)lineIterator.next();

                for (Priority priority : Priority.values()) {
                    if (patterns.containsKey(priority)) {
                        Matcher matcher = patterns.get(priority).matcher(line);
                        if (matcher.matches() && matcher.groupCount() == 2) {
                            String message = matcher.group(2).trim();
                            tasks.add(new Task(priority, lineNumber, matcher.group(1), StringUtils.remove(message, ":").trim()));
                        }
                    }
                }
            }

            return tasks;
        }
        finally {
            reader.close();
        }
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy