Skip to content

Commit

Permalink
feat(project): Reporting Improvements
Browse files Browse the repository at this point in the history
This pull request adds:

- Reporting: Add to License Report List of 3rd Party Components eclipse-sw360#375
- Reporting: License report new structure: cover page eclipse-sw360#377
- Reporting: License report new proposed structure: Sections eclipse-sw360#378
- Reporting: License Report: Add Fixed Template Text eclipse-sw360#379
- Reporting: License Report: Add Editable Default Texts eclipse-sw360#380

closes eclipse-sw360#375
closes eclipse-sw360#377
closes eclipse-sw360#378
closes eclipse-sw360#379
closes eclipse-sw360#380

Signed-off-by: Johannes Amorosa <johannes.amorosa@endocode.com>
  • Loading branch information
Johannes Amorosa committed Nov 12, 2018
1 parent db60f4b commit 8b66392
Show file tree
Hide file tree
Showing 28 changed files with 681 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,16 @@ public class LicenseInfoHandler implements LicenseInfoService.Iface {
private static final int CACHE_TIMEOUT_MINUTES = 15;
private static final int CACHE_MAX_ITEMS = 100;
private static final String DEFAULT_LICENSE_INFO_HEADER_FILE="/DefaultLicenseInfoHeader.txt";
private static final String DEFAULT_LICENSE_INFO_TEXT = loadDefaultLicenseInfoHeaderText();
private static final String DEFAULT_LICENSE_INFO_TEXT = dropCommentedLine(DEFAULT_LICENSE_INFO_HEADER_FILE);
private static final String DEFAULT_OBLIGATIONS_FILE="/DefaultObligations.txt";
private static final String DEFAULT_OBLIGATIONS_TEXT = dropCommentedLine(DEFAULT_OBLIGATIONS_FILE);
public static final String MSG_NO_RELEASE_GIVEN = "No release given";

protected List<LicenseInfoParser> parsers;
protected List<OutputGenerator<?>> outputGenerators;
protected ComponentDatabaseHandler componentDatabaseHandler;
protected Cache<String, List<LicenseInfoParsingResult>> licenseInfoCache;
protected Cache<String, List<ObligationParsingResult>> obligationCache;

public LicenseInfoHandler() throws MalformedURLException {
this(new AttachmentDatabaseHandler(DatabaseSettings.getConfiguredHttpClient(), DatabaseSettings.COUCH_DB_DATABASE, DatabaseSettings.COUCH_DB_ATTACHMENTS),
Expand All @@ -72,6 +75,8 @@ protected LicenseInfoHandler(AttachmentDatabaseHandler attachmentDatabaseHandler
this.componentDatabaseHandler = componentDatabaseHandler;
this.licenseInfoCache = CacheBuilder.newBuilder().expireAfterWrite(CACHE_TIMEOUT_MINUTES, TimeUnit.MINUTES)
.maximumSize(CACHE_MAX_ITEMS).build();
this.obligationCache = CacheBuilder.newBuilder().expireAfterWrite(CACHE_TIMEOUT_MINUTES, TimeUnit.MINUTES)
.maximumSize(CACHE_MAX_ITEMS).build();

AttachmentContentProvider contentProvider = attachment -> attachmentDatabaseHandler.getAttachmentContent(attachment.getAttachmentContentId());

Expand Down Expand Up @@ -104,6 +109,7 @@ public LicenseInfoFile getLicenseInfoFile(Project project, User user, String out
Map<Release, Set<String>> releaseToAttachmentId = mapKeysToReleases(releaseIdsToSelectedAttachmentIds, user);
Collection<LicenseInfoParsingResult> projectLicenseInfoResults = getAllReleaseLicenseInfos(releaseToAttachmentId, user,
excludedLicensesPerAttachment);
Collection<ObligationParsingResult> obligationsResults = getAllReleaseObligations(releaseToAttachmentId, user);

String[] outputGeneratorClassnameAndVariant = outputGenerator.split("::");
if (outputGeneratorClassnameAndVariant.length != 2) {
Expand All @@ -116,8 +122,10 @@ public LicenseInfoFile getLicenseInfoFile(Project project, User user, String out
LicenseInfoFile licenseInfoFile = new LicenseInfoFile();

licenseInfoFile.setOutputFormatInfo(generator.getOutputFormatInfo());
String licenseInfoHeaderText = (project.isSetLicenseInfoHeaderText()) ? project.getLicenseInfoHeaderText() : getDefaultLicenseInfoHeaderText();
Object output = generator.generateOutputFile(projectLicenseInfoResults, project.getName(), project.getVersion(), licenseInfoHeaderText);

fillDefaults(project);

Object output = generator.generateOutputFile(projectLicenseInfoResults, project, obligationsResults);
if (output instanceof byte[]) {
licenseInfoFile.setGeneratedOutput((byte[]) output);
} else if (output instanceof String) {
Expand All @@ -129,6 +137,15 @@ public LicenseInfoFile getLicenseInfoFile(Project project, User user, String out
return licenseInfoFile;
}

private void fillDefaults(Project project) {
if(!project.isSetLicenseInfoHeaderText()) {
project.setLicenseInfoHeaderText(getDefaultLicenseInfoHeaderText());
}
if(!project.isSetObligationsText()) {
project.setObligationsText(getDefaultObligationsText());
}
}

@Override
public List<OutputFormatInfo> getPossibleOutputFormats() {
return outputGenerators.stream().map(OutputGenerator::getOutputFormatInfo).collect(Collectors.toList());
Expand Down Expand Up @@ -188,6 +205,52 @@ public List<LicenseInfoParsingResult> getLicenseInfoForAttachment(Release releas
}
}

private List<ObligationParsingResult> getObligationsForAttachment(Release release, String attachmentContentId, User user)
throws TException {
if (release == null) {
return Collections.singletonList(new ObligationParsingResult()
.setStatus(ObligationInfoRequestStatus.NO_APPLICABLE_SOURCE)
.setMessage(MSG_NO_RELEASE_GIVEN));
}

List<ObligationParsingResult> cachedResults = obligationCache.getIfPresent(attachmentContentId);
if (cachedResults != null) {
return cachedResults;
}

Attachment attachment = nullToEmptySet(release.getAttachments()).stream()
.filter(a -> a.getAttachmentContentId().equals(attachmentContentId)).findFirst().orElseThrow(() -> {
String message = String.format(
"Attachment selected for obligations info generation is not found in release's attachments. Release id: %s. Attachment content id: %s",
release.getId(), attachmentContentId);
return new IllegalStateException(message);
});

try {

List<LicenseInfoParser> applicableParsers = parsers.stream()
.filter(parser -> wrapTException(() -> parser.isApplicableTo(attachment, user, release))).collect(Collectors.toList());

if (applicableParsers.size() == 0) {
LOGGER.warn("No applicable parser has been found for the attachment selected for license information");
return Collections.singletonList(new ObligationParsingResult()
.setStatus(ObligationInfoRequestStatus.NO_APPLICABLE_SOURCE)
.setMessage("No applicable parser has been found for the attachment."));
} else if (applicableParsers.size() > 1) {
LOGGER.info("More than one parser claims to be able to parse attachment with contend id " + attachmentContentId);
}

List<ObligationParsingResult> results = applicableParsers.stream()
.map(parser -> wrapTException(() -> parser.getObligations(attachment, user, release)))
.collect(Collectors.toList());

obligationCache.put(attachmentContentId, results);
return results;
} catch (WrappedTException exception) {
throw exception.getCause();
}
}

private LicenseInfoParsingResult assignFileNameToLicenseInfoParsingResult(LicenseInfoParsingResult licenseInfoParsingResult, String filename) {
if (licenseInfoParsingResult.getLicenseInfo() == null) {
licenseInfoParsingResult.setLicenseInfo(new LicenseInfo());
Expand All @@ -201,6 +264,11 @@ public String getDefaultLicenseInfoHeaderText() {
return DEFAULT_LICENSE_INFO_TEXT;
}

@Override
public String getDefaultObligationsText() {
return DEFAULT_OBLIGATIONS_TEXT;
}

protected Map<Release, Set<String>> mapKeysToReleases(Map<String, Set<String>> releaseIdsToAttachmentIds, User user) throws TException {
Map<Release, Set<String>> result = Maps.newHashMap();
try {
Expand Down Expand Up @@ -243,6 +311,21 @@ protected Collection<LicenseInfoParsingResult> getAllReleaseLicenseInfos(Map<Rel
return results;
}

protected Collection<ObligationParsingResult> getAllReleaseObligations(Map<Release, Set<String>> releaseToSelectedAttachmentIds, User user)
throws TException {
List<ObligationParsingResult> results = Lists.newArrayList();

for (Entry<Release, Set<String>> entry : releaseToSelectedAttachmentIds.entrySet()) {
for (String attachmentContentId : entry.getValue()) {
if (attachmentContentId != null) {
results.addAll(getObligationsForAttachment(entry.getKey(), attachmentContentId, user));
}
}
}

return results;
}

protected LicenseInfoParsingResult filterLicenses(LicenseInfoParsingResult result, Set<LicenseNameWithText> licencesToExclude) {
// make a deep copy to NOT change the original document that is cached
LicenseInfoParsingResult newResult = result.deepCopy();
Expand Down Expand Up @@ -301,9 +384,9 @@ protected OutputGenerator<?> getOutputGeneratorByClassnameAndVariant(String gene
.findFirst().orElseThrow(() -> new TException("Unknown output generator: " + generatorClassname));
}

private static String loadDefaultLicenseInfoHeaderText(){
String defaultLicenseInfoHeader = new String( CommonUtils.loadResource(LicenseInfoHandler.class, DEFAULT_LICENSE_INFO_HEADER_FILE).orElse(new byte[0]) );
defaultLicenseInfoHeader = defaultLicenseInfoHeader.replaceAll("(?m)^#.*\\n", ""); // ignore comments in template file
return defaultLicenseInfoHeader;
private static String dropCommentedLine(String TEMPLATE_FILE) {
String text = new String( CommonUtils.loadResource(LicenseInfoHandler.class, TEMPLATE_FILE).orElse(new byte[0]) );
text = text.replaceAll("(?m)^#.*\\n", ""); // ignore comments in template file
return text;
}
}
Loading

0 comments on commit 8b66392

Please sign in to comment.