/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.motorolamobility.preflighting.internal.commandoutput;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.util.List;
import com.motorolamobility.preflighting.core.exception.PreflightingToolException;
import com.motorolamobility.preflighting.core.logging.PreflightingLogger;
import com.motorolamobility.preflighting.core.validation.ApplicationValidationResult;
import com.motorolamobility.preflighting.core.validation.Parameter;
import com.motorolamobility.preflighting.core.validation.ValidationResult;
import com.motorolamobility.preflighting.core.validation.ValidationResultData;
import com.motorolamobility.preflighting.core.validation.ValidationResultData.SEVERITY;
import com.motorolamobility.preflighting.core.verbose.DebugVerboseOutputter;
import com.motorolamobility.preflighting.core.verbose.DebugVerboseOutputter.VerboseLevel;
import com.motorolamobility.preflighting.core.verbose.WarningLevelFilter;
import com.motorolamobility.preflighting.i18n.PreflightingNLS;
import com.motorolamobility.preflighting.output.AbstractOutputter;
public class CSVOutputter extends AbstractOutputter
{
private static final int MAX_PREVIEW_LENGTH = 120;
/**
* Line separator
*/
private final String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$
/**
* CSV separator
*/
private final String DELIMITER = ",";
/**
* Quote string
*/
private final String QUOTES = "\"";
/**
* Backslash string
*/
private final String BACKSLASH = "\\";
/**
* I/O Exception message logging.
*/
private final String IO_ERROR = PreflightingNLS.TextOutputter_IOExceptionMessage;
/**
* Exception stating that it was not possible to print the results.
*/
private final String PRINT_ERROR = PreflightingNLS.TextOutputter_PrintResultsErrorMessage;
/**
* Writer used for output
*/
private BufferedWriter writer = null;
private enum CSV_FIELDS
{
type
{
@Override
public String toString()
{
return "type";
}
},
checker
{
@Override
public String toString()
{
return "checker_id";
}
},
condition
{
@Override
public String toString()
{
return "condition";
}
},
description
{
@Override
public String toString()
{
return "description";
}
},
file
{
@Override
public String toString()
{
return "file";
}
},
line
{
@Override
public String toString()
{
return "line";
}
},
preview
{
@Override
public String toString()
{
return "preview";
}
},
suggestion
{
@Override
public String toString()
{
return "suggestion";
}
}
}
/* (non-Javadoc)
* @see com.motorolamobility.preflighting.core.commandoutput.IOutputter#print(java.util.Map, java.io.OutputStream, java.util.List)
*/
@Override
public void print(ApplicationValidationResult results, OutputStream stream,
List<Parameter> parameters) throws PreflightingToolException
{
initializeParams(parameters);
// Use a BufferedWriter to write the results
writer = new BufferedWriter(new OutputStreamWriter(stream));
try
{
if (results.getResults().size() > 0)
{
printCSVHeader();
for (ValidationResult checker : results.getResults())
{
printCheckerResultCSV(checker);
}
}
/*
TextOutputter.printExecutionReport(results.getExecutionStatus(), errorStream);
*/
}
catch (IOException e)
{
PreflightingLogger.error(getClass(), IO_ERROR + e.getMessage());
throw new PreflightingToolException(PRINT_ERROR, e);
}
finally
{
try
{
writer.close();
//to help Garbage Collector to work
writer = null;
}
catch (IOException e)
{
PreflightingLogger.error(getClass(), IO_ERROR + e.getMessage());
}
}
}
/**
* Prints the CSV fields.
*/
private void printCSVHeader() throws IOException
{
StringBuilder stringBuilder = new StringBuilder();
// Append results message
CSV_FIELDS[] fields = CSV_FIELDS.values();
DebugVerboseOutputter.printVerboseMessage("", VerboseLevel.v1);
for (int i = 0; i < fields.length; i++)
{
if (fields[i].compareTo(CSV_FIELDS.suggestion) == 0)
{
if (WarningLevelFilter.printQuickFixSuggestions())
{
stringBuilder.append(QUOTES + fields[i].toString() + QUOTES + DELIMITER);
}
}
else
{
stringBuilder.append(QUOTES + fields[i].toString() + QUOTES + DELIMITER);
}
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
stringBuilder.append(NEWLINE);
writer.write(stringBuilder.toString());
}
private void printCheckerResultCSV(ValidationResult validationResult) throws IOException
{
List<ValidationResultData> data = validationResult.getValidationResult();
if (data.size() > 0)
{
StringBuilder stringBuilder = new StringBuilder();
for (ValidationResultData d : data)
{
if (getApplicationFile() != null)
{
//No files were issued
if (d.getFileToIssueLines().keySet().isEmpty())
{
printCSVLine(stringBuilder, d, validationResult, null, null);
}
else
{
// Iterate through the list of files
for (File resource : d.getFileToIssueLines().keySet())
{
String fileLocation = computeResourcePath(resource);
// Number of occurrences
List<Integer> lines = d.getFileToIssueLines().get(resource);
if (lines.isEmpty())
{
printCSVLine(stringBuilder, d, validationResult, fileLocation, null);
}
else
{
for (Integer currentLine : lines)
{
printCSVLine(stringBuilder, d, validationResult, fileLocation,
currentLine);
}
}
}
}
}
writer.write(stringBuilder.toString());
writer.flush();
// Clean string builder
stringBuilder.delete(0, stringBuilder.length());
}
}
}
/**
* Prints each line of the CSV output.
*/
private void printCSVLine(StringBuilder stringBuilder, ValidationResultData resultData,
ValidationResult validationResult, String fileLocation, Integer currentLine)
{
if (!resultData.getSeverity().equals(SEVERITY.OK))
{
// Append severity
stringBuilder.append(QUOTES + resultData.getSeverity().toString() + QUOTES + DELIMITER);
//checker id
stringBuilder.append(QUOTES + validationResult.getCheckerId() + QUOTES + DELIMITER);
//condition
stringBuilder.append(QUOTES + resultData.getConditionID() + QUOTES + DELIMITER);
// Append result description
if (resultData.getIssueDescription() != null)
{
stringBuilder.append(QUOTES + escapeQuotes(resultData.getIssueDescription())
+ QUOTES);
}
stringBuilder.append(DELIMITER);
if (fileLocation != null)
{
stringBuilder.append(QUOTES + fileLocation + QUOTES);
}
stringBuilder.append(DELIMITER);
if (currentLine != null)
{
stringBuilder.append(QUOTES + currentLine + QUOTES);
}
stringBuilder.append(DELIMITER);
String preview = resultData.getPreview();
if (preview != null)
{
stringBuilder.append(QUOTES
+ escapeQuotes(preview.length() > MAX_PREVIEW_LENGTH ? preview.substring(0,
MAX_PREVIEW_LENGTH) : preview) + QUOTES);
}
//stringBuilder.append(DELIMITER);
/* Removing infoUrl from non-xml outputters
if (resultData.getInfoURL() != null)
{
stringBuilder.append(QUOTES + escapeQuotes(resultData.getInfoURL()) + QUOTES);
}
*/
if (WarningLevelFilter.printQuickFixSuggestions())
{
stringBuilder.append(DELIMITER);
if (resultData.getQuickFixSuggestion() != null)
{
stringBuilder.append(QUOTES + escapeQuotes(resultData.getQuickFixSuggestion())
+ QUOTES);
}
}
stringBuilder.append(NEWLINE);
}
}
/**
* Escape quotes from a given string
* @param textToEscape string that may contain quotes to be escaped
* @return
*/
private String escapeQuotes(String textToEscape)
{
StringBuilder strBuilder = new StringBuilder();
if (textToEscape.indexOf(QUOTES) != -1)
{
String[] splitedStr = textToEscape.split(QUOTES);
for (int i = 0; i < (splitedStr.length - 1); i++)
{
strBuilder.append(splitedStr[i] + BACKSLASH + QUOTES);
}
strBuilder.append(splitedStr[splitedStr.length - 1]);
//special case where the text ends with a quote
if (textToEscape.endsWith(QUOTES))
{
strBuilder.append(BACKSLASH + QUOTES);
}
textToEscape = strBuilder.toString();
}
return textToEscape;
}
@Override
public void printError(Exception exceptionThrown, PrintStream out)
{
// TODO Auto-generated method stub
}
}