View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.renderers;
    5
    6   import java.io.IOException;
    7   import java.util.ArrayList;
    8   import java.util.HashMap;
    9   import java.util.Iterator;
    10  import java.util.List;
    11  import java.util.Map;
    12
    13  import net.sourceforge.pmd.PMD;
    14  import net.sourceforge.pmd.PropertySource;
    15  import net.sourceforge.pmd.RuleViolation;
    16  import net.sourceforge.pmd.lang.rule.properties.BooleanProperty;
    17  import net.sourceforge.pmd.renderers.ColumnDescriptor.Accessor;
    18  import net.sourceforge.pmd.util.StringUtil;
    19
    20  /**
    21   * Renderer the results to a comma-delimited text format. All available columns
    22   * are present by default. IDEs can enable/disable columns individually (cmd-line
    23   * control to follow eventually)
    24   */
    25  public class CSVRenderer extends AbstractIncrementingRenderer {
    26
    27      private String separator;
    28      private String cr;
    29
    30      private CSVWriter<RuleViolation> csvWriter;
    31
    32      private static final String DefaultSeparator = ",";
    33
    34      private static final Map<String, BooleanProperty> propertyDescriptorsById = new HashMap<String, BooleanProperty>();
    35
    36      public static final String NAME = "csv";
    37
    38      @SuppressWarnings("unchecked")
    39  	private static final ColumnDescriptor<RuleViolation>[] AllColumns = new ColumnDescriptor[] {
    40      	new ColumnDescriptor<RuleViolation>("problem", 	"Problem", 		new Accessor<RuleViolation>() { public String get(int idx, RuleViolation rv, String cr) { return Integer.toString(idx); }} ),
    41      	new ColumnDescriptor<RuleViolation>("package",	"Package", 		new Accessor<RuleViolation>() { public String get(int idx, RuleViolation rv, String cr) { return rv.getPackageName(); }} ),
    42      	new ColumnDescriptor<RuleViolation>("file",		"File", 		new Accessor<RuleViolation>() { public String get(int idx, RuleViolation rv, String cr) { return rv.getFilename(); }} ),
    43      	new ColumnDescriptor<RuleViolation>("priority",	"Priority", 	new Accessor<RuleViolation>() { public String get(int idx, RuleViolation rv, String cr) { return Integer.toString(rv.getRule().getPriority().getPriority()); }} ),
    44      	new ColumnDescriptor<RuleViolation>("line",		"Line", 		new Accessor<RuleViolation>() { public String get(int idx, RuleViolation rv, String cr) { return Integer.toString(rv.getBeginLine()); }} ),
    45      	new ColumnDescriptor<RuleViolation>("desc",		"Description", 	new Accessor<RuleViolation>() { public String get(int idx, RuleViolation rv, String cr) { return StringUtil.replaceString(rv.getDescription(), '\"', "'"); }} ),
    46      	new ColumnDescriptor<RuleViolation>("ruleSet",	"Rule set", 	new Accessor<RuleViolation>() { public String get(int idx, RuleViolation rv, String cr) { return rv.getRule().getRuleSetName(); }} ),
    47      	new ColumnDescriptor<RuleViolation>("rule",		"Rule", 		new Accessor<RuleViolation>() { public String get(int idx, RuleViolation rv, String cr) { return rv.getRule().getName(); }} )
    48      	};
    49
    50
    51      private static BooleanProperty booleanPropertyFor(String id, String label) {
    52
    53      	BooleanProperty prop = propertyDescriptorsById.get(id);
    54      	if (prop != null) return prop;
    55
    56      	prop = new BooleanProperty(id, "Include " + label + " column", true, 1.0f);
    57      	propertyDescriptorsById.put(id, prop);
    58      	return prop;
    59      }
    60
    61      public CSVRenderer(ColumnDescriptor<RuleViolation>[] columns, String theSeparator, String theCR) {
    62      	super(NAME, "Comma-separated values tabular format.");
    63
    64      	separator = theSeparator;
    65      	cr = theCR;
    66
    67      	for (ColumnDescriptor<RuleViolation> desc : columns) {
    68      		definePropertyDescriptor(booleanPropertyFor(desc.id, desc.title));
    69      		}
    70      }
    71
    72      private List<ColumnDescriptor<RuleViolation>> activeColumns() {
    73
    74      	List<ColumnDescriptor<RuleViolation>> actives = new ArrayList<ColumnDescriptor<RuleViolation>>();
    75
    76       	for (ColumnDescriptor<RuleViolation> desc : AllColumns) {
    77      		BooleanProperty prop = booleanPropertyFor(desc.id, null);
    78      		if (getProperty(prop)) {
    79      			actives.add(desc);
    80      			} else {
    81  //    				System.out.println("disabled: " + prop);
    82      			}
    83      		}
    84       	return actives;
    85      }
    86
    87      private CSVWriter<RuleViolation> csvWriter() {
    88      	if (csvWriter != null) return csvWriter;
    89
    90      	csvWriter = new CSVWriter<RuleViolation>(activeColumns(), separator, cr);
    91      	return csvWriter;
    92      }
    93
    94      public CSVRenderer() {
    95      	this( AllColumns, DefaultSeparator, PMD.EOL);
    96      }
    97
    98      /**
    99       * {@inheritDoc}
    100      */
    101     @Override
    102     public void start() throws IOException {
    103     	csvWriter().writeTitles(getWriter());
    104     }
    105
    106     public String defaultFileExtension() { return "csv"; }
    107
    108     /**
    109      * {@inheritDoc}
    110      */
    111     @Override
    112     public void renderFileViolations(Iterator<RuleViolation> violations) throws IOException {
    113     	csvWriter().writeData(getWriter(), violations);
    114     }
    115
    116 	 /**
    117 	  * We can't show any violations if we don't have any visible columns.
    118 	  *
    119 	  * @see PropertySource#dysfunctionReason()
    120 	  */
    121     @Override
    122 	 public String dysfunctionReason() {
    123 		 return activeColumns().isEmpty() ? "No columns selected" : null;
    124 	 }
    125 }