Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide JSON as an option to generate report #972

Merged
merged 2 commits into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ private static void checkOptionsIn(CommandLine commandLine) {
}

if (commandLine.hasOption("report-type")
&& !asList("text", "markdown").contains(commandLine.getOptionValue("report-type"))) {
&& !asList("text", "markdown", "json").contains(
commandLine.getOptionValue("report-type"))) {

throw new IllegalArgumentException(
format("Unknown report type: %s", commandLine.getOptionValue("report-type")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
import com.sap.oss.phosphor.fosstars.model.rating.oss.OssSecurityRating;
import com.sap.oss.phosphor.fosstars.model.subject.oss.GitHubProject;
import com.sap.oss.phosphor.fosstars.tool.format.Formatter;
import com.sap.oss.phosphor.fosstars.tool.format.JsonPrettyPrinter;
import com.sap.oss.phosphor.fosstars.tool.format.OssSecurityRatingMarkdownFormatter;
import com.sap.oss.phosphor.fosstars.tool.format.PrettyPrinter;
import com.sap.oss.phosphor.fosstars.tool.report.MergedJsonReporter;
import com.sap.oss.phosphor.fosstars.tool.report.OssSecurityRatingJsonReporter;
import com.sap.oss.phosphor.fosstars.tool.report.OssSecurityRatingMarkdownReporter;
import com.sap.oss.phosphor.fosstars.tool.report.Reporter;
import java.io.File;
Expand Down Expand Up @@ -177,6 +179,8 @@ Formatter createFormatter(String type) {
return PrettyPrinter.withVerboseOutput(OSS_SECURITY_GITHUB_ADVISOR);
case "markdown":
return new OssSecurityRatingMarkdownFormatter(OSS_SECURITY_GITHUB_ADVISOR);
case "json":
return new JsonPrettyPrinter(OSS_SECURITY_GITHUB_ADVISOR);
default:
throw new IllegalArgumentException(format("Unsupported report type: %s", type));
}
Expand All @@ -192,6 +196,10 @@ Optional<Reporter<GitHubProject>> reporterFrom(ReportConfig reportConfig) throws
return Optional.of(
new OssSecurityRatingMarkdownReporter(reportConfig.where, reportConfig.source,
rating(), OSS_SECURITY_GITHUB_ADVISOR));
case JSON_REPORT:
return Optional.of(
new OssSecurityRatingJsonReporter(reportConfig.where, reportConfig.source,
rating(), OSS_SECURITY_GITHUB_ADVISOR));
default:
logger.warn("Oops! That's an unknown type of report: {}", reportConfig.type);
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class ReportConfig {
* Types of reports.
*/
public enum ReportType {
MARKDOWN, JSON, ISSUES
MARKDOWN, JSON, ISSUES, JSON_REPORT
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static com.sap.oss.phosphor.fosstars.tool.format.Markdown.DOUBLE_NEW_LINE;
import static com.sap.oss.phosphor.fosstars.tool.format.Markdown.NEW_LINE;
import static java.lang.String.format;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;

import com.sap.oss.phosphor.fosstars.advice.Advice;
Expand All @@ -29,12 +30,20 @@
import java.util.TreeSet;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
* A base class for Markdown formatters.
*/
public abstract class AbstractMarkdownFormatter extends CommonFormatter {

/**
* A logger.
*/
private static final Logger LOGGER
= LogManager.getLogger(AbstractMarkdownFormatter.class);

/**
* Create a new formatter.
*
Expand Down Expand Up @@ -67,7 +76,7 @@ protected MarkdownElement markdownAdviceFor(Subject subject) {
throw new UncheckedIOException("Oops! Could not print advice!", e);
}

if (adviceList.isEmpty()) {
if (adviceList == null || adviceList.isEmpty()) {
return MarkdownString.EMPTY;
}

Expand All @@ -85,6 +94,21 @@ protected MarkdownElement markdownAdviceFor(Subject subject) {
return Markdown.section().with(markdownAdviceHeader()).thatContains(advice);
}

/**
* Extract advices for a subject.
*
* @param subject The subject.
* @return Advices collected form a subject.
*/
protected List<Advice> adviceFor(Subject subject) {
try {
return advisor.adviceFor(subject);
} catch (IOException e) {
LOGGER.warn("Oops! Could not collect advices!", e);
return emptyList();
}
}

/**
* Convert links from advice to Markdown elements.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
package com.sap.oss.phosphor.fosstars.tool.format;

import static java.util.Collections.emptyList;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sap.oss.phosphor.fosstars.advice.Advice;
import com.sap.oss.phosphor.fosstars.advice.AdviceContent;
import com.sap.oss.phosphor.fosstars.advice.Advisor;
import com.sap.oss.phosphor.fosstars.model.Subject;
import com.sap.oss.phosphor.fosstars.model.Value;
import com.sap.oss.phosphor.fosstars.model.value.RatingValue;
import com.sap.oss.phosphor.fosstars.model.value.ScoreValue;
import com.sap.oss.phosphor.fosstars.tool.format.model.Advices;
import com.sap.oss.phosphor.fosstars.tool.format.model.Feature;
import com.sap.oss.phosphor.fosstars.tool.format.model.Rating;
import com.sap.oss.phosphor.fosstars.tool.format.model.Score;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.text.DecimalFormat;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
* The class prints a pretty rating value in JSON.
*/
public class JsonPrettyPrinter extends CommonFormatter {

/**
* Object Mapper for Json.
*/
private static final ObjectMapper mapper = new ObjectMapper();

/**
* A logger.
*/
private static final Logger LOGGER
= LogManager.getLogger(JsonPrettyPrinter.class);

/**
* A formatter for doubles.
*/
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.#");

static {
DECIMAL_FORMAT.setMinimumFractionDigits(1);
DECIMAL_FORMAT.setMaximumFractionDigits(2);
}

/**
* Initializes a pretty printer.
*
* @param advisor to be added to the printed output.
*/
public JsonPrettyPrinter(Advisor advisor) {
super(advisor);
}

@Override
public String print(Subject subject) {
if (!subject.ratingValue().isPresent()) {
return StringUtils.EMPTY;
}
RatingValue ratingValue = subject.ratingValue().get();
Rating rating = from(ratingValue, subject);
rating.advices(adviceFor(subject));
StringBuilder output = new StringBuilder();
try {
output.append(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rating));
} catch (JsonProcessingException e) {
throw new UncheckedIOException(
"Oops! Could not parse the rating value object to Json string!", e);
}

return output.toString();
}

/**
* Extract advices for a subject.
*
* @param subject The subject.
* @return Advices collected form a subject.
*/
private List<Advices> adviceFor(Subject subject) {
try {
return advisor.adviceFor(subject).stream().map(JsonPrettyPrinter::from)
.collect(Collectors.toList());
} catch (IOException e) {
LOGGER.warn("Oops! Could not collect advices!", e);
return emptyList();
}
}

/**
* Map Advice to serializable class.
*
* @param advice The Advice.
* @return The serializable class.
*/
private static Advices from(Advice advice) {
AdviceContent content = advice.content();
return new Advices(content.text(), content.feature().name(), content.links());
}

/**
* Format a rating value.
*
* @param ratingValue The rating value.
* @param subject The subject.
* @return A formatted rating value.
*/
private static Rating from(RatingValue ratingValue, Subject subject) {
ScoreValue scoreValue = ratingValue.scoreValue();
Rating rating = new Rating()
.purl(subject.purl())
.label(ratingValue.label().name());
Score score = from(scoreValue);
rating.score(score);
return rating;
}

/**
* Extract Score from Score Value.
*
* @param scoreValue The score value.
* @return the serializable Score.
*/
private static Score from(ScoreValue scoreValue) {
Score score = new Score()
.name(scoreValue.score().name())
.value(tellMeActualValueOf(scoreValue))
.confidence(printValue(scoreValue.confidence()))
.weight(printValue(scoreValue.weight()));
from(scoreValue, score);
return score;
}

/**
* Map feature value to serializable class.
*
* @param featureValue The feature value.
* @return The serializable class from feature value.
*/
private static Feature from(Value<?> featureValue) {
return new Feature()
.name(featureValue.feature().name())
.value(tellMeActualValueOf(featureValue));
}

/**
* Extract Sub scores from the score value.
*
* @param scoreValue The score value to be printed.
* @param score Tells if the score is a top-level score in the rating.
*/
private static void from(ScoreValue scoreValue, Score score) {
for (Value<?> usedValue : scoreValue.usedValues()) {
if (usedValue instanceof ScoreValue) {
score.subScore(from((ScoreValue) usedValue));
} else {
score.feature(from(usedValue));
}
}
}

/**
* Prints an actual value of a score value. The method takes care about unknown and not-applicable
* score values.
*
* @param scoreValue The score value.
* @return A string that represents the score value.
*/
public static String tellMeActualValueOf(ScoreValue scoreValue) {
if (scoreValue.isNotApplicable()) {
return "N/A";
}

if (scoreValue.isUnknown()) {
return "unknown";
}

return printValue(scoreValue.get());
}

/**
* Prints an actual value. The method takes care about unknown and not-applicable values.
*
* @param value The value.
* @return A string that represents the score value.
*/
public static String tellMeActualValueOf(Value<?> value) {
if (value.isNotApplicable()) {
return "N/A";
}

if (value.isUnknown()) {
return "unknown";
}

return String.format("%s", value.get());
}

/**
* Prints out a number with its max value.
*
* @param value The number.
* @return A formatted string with the number and max value.
*/
public static String printValue(double value) {
return String.format("%-4s",
DECIMAL_FORMAT.format(value));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import static com.sap.oss.phosphor.fosstars.tool.format.Markdown.SPACE;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.unmodifiableMap;
import static java.util.Objects.requireNonNull;
Expand Down Expand Up @@ -46,8 +45,6 @@
import java.util.Set;
import java.util.function.BooleanSupplier;
import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
* The class prints a rating value
Expand All @@ -67,12 +64,6 @@ public class OssRulesOfPlayRatingMarkdownFormatter extends AbstractMarkdownForma
private static final String DEFAULT_RATING_VALUE_TEMPLATE
= loadFrom(RATING_VALUE_TEMPLATE_RESOURCE, OssRulesOfPlayRatingMarkdownFormatter.class);

/**
* A logger.
*/
private static final Logger LOGGER
= LogManager.getLogger(OssRulesOfPlayRatingMarkdownFormatter.class);

/**
* Maps a rule to its identifier.
*/
Expand Down Expand Up @@ -192,21 +183,6 @@ String print(RatingValue ratingValue, List<Advice> advice) {
.replace("%ADVICE%", makeAdviceFrom(violations, warnings, passedRules, unclearRules));
}

/**
* Looks for advice for a subject.
*
* @param subject The subject.
* @return A list of advice.
*/
private List<Advice> adviceFor(Subject subject) {
try {
return advisor.adviceFor(subject);
} catch (IOException e) {
LOGGER.warn("Oops! Could not print advice!", e);
return emptyList();
}
}

/**
* Convert a list of formatted rules to Markdown-formatted advice.
*
Expand Down
Loading