gov.nih.nci.ncicb.tcga.dcc.common.util.IssueScanner.java Source code

Java tutorial

Introduction

Here is the source code for gov.nih.nci.ncicb.tcga.dcc.common.util.IssueScanner.java

Source

/*
 * Software License, Version 1.0 Copyright 2010 SRA International, Inc.
 * Copyright Notice.  The software subject to this notice and license includes both human
 * readable source code form and machine readable, binary, object code form (the "caBIG
 * Software").
 *
 * Please refer to the complete License text for full details at the root of the project.
 */

package gov.nih.nci.ncicb.tcga.dcc.common.util;

import org.apache.commons.io.IOUtils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author Robert S. Sfeir
 * @version 1.0
 *          <p/>
 *          A class file to scan emails sent from GForge to turn them into a comma delimited file for import into Jira.
 */
public class IssueScanner {
    private Scanner fileScanner;
    private final ArrayList<Issue> issueList = new ArrayList<Issue>();
    private Issue theIssue;
    private static final String FILE_SYSTEM_LOCATION = System.getProperty("user.dir") + File.separator;
    private static final String QUOTE = "\"";
    private static final String COMMA = ",";

    /**
     * Scan a file containing emails from gforge. Simply reads the file line by line and allows us to parse each line
     * for specific values we're interested in importing into Jira.
     *
     * @param theIssueFile the file we want to scan
     * @throws IOException thrown when the file is not found, or we could not write a file out when done.
     */
    public void scanFile(final File theIssueFile) throws IOException {
        try {
            fileScanner = new Scanner(theIssueFile);
            while (fileScanner.hasNextLine()) {
                processTheLine(fileScanner.nextLine());
            }
        } finally {
            if (issueList.size() > 0) {
                writeCommaDelimitedFile();
            }
            fileScanner.close();
        }
    }

    public static void main(final String args[]) throws IOException {
        final IssueScanner is = new IssueScanner();
        is.scanFile(new File(FILE_SYSTEM_LOCATION + args[0]));
    }

    /**
     * Looks at the string on the line and determined certain values from it and deals with them appropriately. There is
     * one special case and that is when we hit the Comment: section.  That section is multiple lines and we need to
     * tell the scanner to keep going.  Because of that we force a scan read forward until the end of the emai. While
     * the scanner is going forward we're adding the comments to a String Builder before adding it to the comments field
     * in the issue bean.
     *
     * @param theLine the line we just read and we need to parse out.
     */
    private void processTheLine(final String theLine) {
        if (theIssue == null) {
            theIssue = new Issue();
        }
        if (isAMatch("Status:", theLine.trim())) {
            //This status will be mapped in Jira to one that you think is appropriate.  Generally, we use Needs Triage
            //as our starting entry point.
            theIssue.setStatus(fieldValue(theLine));
        } else if (isAMatch("Priority:", theLine.trim())) {
            theIssue.setPriority(fieldValue(theLine));
        } else if (isAMatch("Summary:", theLine.trim())) {
            theIssue.setSummary(fieldValue(theLine));
        } else if (isAMatch("Submitted By:", theLine.trim())) {
            theIssue.setSubmittedBy(fieldValue(theLine));
        } else if (isAMatch("Product:", theLine.trim())) {
            theIssue.setProduct(fieldValue(theLine));
        } else if (isAMatch("Component:", theLine.trim())) {
            theIssue.setComponent(fieldValue(theLine));
        } else if (isAMatch("Submitted By:", theLine.trim())) {
            theIssue.setSubmittedBy(fieldValue(theLine));
        } else if (isAMatch("Initial Comment:", theLine.trim())) {
            //This is a special case because after the comment comes a bunch of info which we need to grab into this one field.
            //We're going to try to keep reading the lines until we get to the end of the email and then break.
            final StringBuilder theFullComment = new StringBuilder();
            while (fileScanner.hasNextLine()) {
                final String theLineToAdd = fileScanner.nextLine();
                if (!isAMatch("You can respond by visiting:", theLineToAdd)) {
                    //Since we're reading line by line, be sure to add a \n to the end of it that will give us a clean
                    //format in Jira.
                    theFullComment.append(theLineToAdd).append("\n");
                } else {
                    //We found the end of the email
                    //Add the issue to the list, clear the issue object and break so we go back to reading.
                    theIssue.setComment(theFullComment.toString());
                    issueList.add(theIssue);
                    theIssue = null;
                    break;
                }
            }
        }
    }

    /**
     * Checks to see if a particular string matches a value we're looking for and returns a boolean. We only need to
     * look at the start of a line since all fields generated by gforge in the email are always at the start of a line.
     *
     * @param lookFor             the value we're interested in.
     * @param theStringToLookInto the String that contains the value
     * @return true or false based on a match.
     */
    private static boolean isAMatch(final String lookFor, final String theStringToLookInto) {
        return theStringToLookInto.startsWith(lookFor);
    }

    /**
     * Return the value after the field name we're looking for and trims out any excess starting or trailing spaces.
     *
     * @param theLine theLine we want to get the value for.
     * @return the value of the field that is contained after the : .
     */
    private static String fieldValue(final String theLine) {
        return theLine.substring(theLine.indexOf(":") + 1).trim();
    }

    /**
     * Call this when you're done creating all the Issues.  This creates an output stream and writes out the beans one
     * by one calling each bean's toString() which returns a comma delimited string of the values contained in that
     * bean. This method also prints out the header of the file before looping over the beans.
     *
     * @throws java.io.IOException if we're not able to write the file out.
     */
    private void writeCommaDelimitedFile() throws IOException {

        AtomicReference<BufferedWriter> out = null;
        FileWriter fileWriter = null;
        BufferedWriter bufferedWriter = null;
        try {
            // Create file
            //noinspection IOResourceOpenedButNotSafelyClosed
            fileWriter = new FileWriter(FILE_SYSTEM_LOCATION + "gforge-issues" + new Date().toString() + ".txt");
            final AtomicReference<FileWriter> fstream = new AtomicReference<FileWriter>(fileWriter);
            //noinspection IOResourceOpenedButNotSafelyClosed
            bufferedWriter = new BufferedWriter(fstream.get());
            out = new AtomicReference<BufferedWriter>(bufferedWriter);
            out.get().write(getHeader());
            for (final Issue anIssue : issueList) {
                out.get().write(anIssue.toString());
            }
        } finally {
            out.get().close();
            IOUtils.closeQuietly(fileWriter);
            IOUtils.closeQuietly(bufferedWriter);
        }
    }

    /**
     * Creates the header for the issue file with comma delimited values.
     *
     * @return the fields for the header separated by commas encapsulated in quotes.
     */
    public static String getHeader() {
        final StringBuilder builtIssueString = new StringBuilder();
        return builtIssueString.append(QUOTE + "Summary" + QUOTE).append(COMMA).append(QUOTE + "Assignee" + QUOTE)
                .append(COMMA).append(QUOTE + "Component" + QUOTE).append(COMMA).append(QUOTE + "Product" + QUOTE)
                .append(COMMA).append(QUOTE + "Priority" + QUOTE).append(COMMA).append(QUOTE + "Status" + QUOTE)
                .append(COMMA).append(QUOTE + "Reporter" + QUOTE).append(COMMA)
                .append(QUOTE + "Description" + QUOTE).append("\n").toString();
    }
}