Skip to content
This repository has been archived by the owner on Jul 25, 2018. It is now read-only.

Commit

Permalink
feat(licenseinfo): Added license todos to DOCX template generation
Browse files Browse the repository at this point in the history
- list of all releases
(name of component, version of component, copyright of component)
- detailed list of releases
(name and version of component, license, todos, acknowledges)
- add project name and version to text/xhtml generator
  • Loading branch information
maierthomas committed Mar 1, 2018
1 parent 51c7edb commit eb71cf2
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 81 deletions.
Expand Up @@ -11,6 +11,7 @@
package org.eclipse.sw360.licenseinfo;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Enums;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
Expand All @@ -28,10 +29,7 @@
import org.eclipse.sw360.datahandler.thrift.licenseinfo.*;
import org.eclipse.sw360.datahandler.thrift.projects.Project;
import org.eclipse.sw360.datahandler.thrift.users.User;
import org.eclipse.sw360.licenseinfo.outputGenerators.DocxGenerator;
import org.eclipse.sw360.licenseinfo.outputGenerators.OutputGenerator;
import org.eclipse.sw360.licenseinfo.outputGenerators.TextGenerator;
import org.eclipse.sw360.licenseinfo.outputGenerators.XhtmlGenerator;
import org.eclipse.sw360.licenseinfo.outputGenerators.*;
import org.eclipse.sw360.licenseinfo.parsers.*;
import org.eclipse.sw360.licenseinfo.util.LicenseNameWithTextUtils;

Expand All @@ -44,6 +42,8 @@
import static org.eclipse.sw360.datahandler.common.CommonUtils.nullToEmptySet;
import static org.eclipse.sw360.datahandler.common.SW360Assert.assertNotNull;
import static org.eclipse.sw360.datahandler.common.WrappedException.wrapTException;
import static org.eclipse.sw360.datahandler.thrift.licenseinfo.OutputFormatVariant.REPORT;
import static org.eclipse.sw360.datahandler.thrift.licenseinfo.OutputFormatVariant.DISCLOSURE;

/**
* Implementation of the Thrift service
Expand Down Expand Up @@ -83,28 +83,36 @@ protected LicenseInfoHandler(AttachmentDatabaseHandler attachmentDatabaseHandler
);

outputGenerators = Lists.newArrayList(
new TextGenerator(),
new XhtmlGenerator(),
new DocxGenerator()
new TextGenerator(DISCLOSURE, "License Disclosure as TEXT"),
new XhtmlGenerator(DISCLOSURE, "License Disclosure as XHTML"),
new DocxGenerator(DISCLOSURE, "License Disclosure as DOCX"),
new DocxGenerator(REPORT, "License Report as DOCX")
);
// @formatter:on
}

@Override
public LicenseInfoFile getLicenseInfoFile(Project project, User user, String outputGeneratorClassName,
Map<String, Set<String>> releaseIdsToSelectedAttachmentIds, Map<String, Set<LicenseNameWithText>> excludedLicensesPerAttachment)
public LicenseInfoFile getLicenseInfoFile(Project project, User user, String outputGenerator,
Map<String, Set<String>> releaseIdsToSelectedAttachmentIds, Map<String, Set<LicenseNameWithText>> excludedLicensesPerAttachment)
throws TException {
assertNotNull(project);
assertNotNull(user);
assertNotNull(outputGeneratorClassName);
assertNotNull(outputGenerator);
assertNotNull(releaseIdsToSelectedAttachmentIds);
assertNotNull(excludedLicensesPerAttachment);

Map<Release, Set<String>> releaseToAttachmentId = mapKeysToReleases(releaseIdsToSelectedAttachmentIds, user);
Collection<LicenseInfoParsingResult> projectLicenseInfoResults = getAllReleaseLicenseInfos(releaseToAttachmentId, user,
excludedLicensesPerAttachment);

OutputGenerator<?> generator = getOutputGeneratorByClassname(outputGeneratorClassName);
String[] outputGeneratorClassnameAndVariant = outputGenerator.split("::");
if (outputGeneratorClassnameAndVariant.length != 2) {
throw new TException("Unsupported output generator value: " + outputGenerator);
}

String outputGeneratorClassName = outputGeneratorClassnameAndVariant[0];
OutputFormatVariant outputGeneratorVariant = Enums.getIfPresent(OutputFormatVariant.class, outputGeneratorClassnameAndVariant[1]).orNull();
OutputGenerator<?> generator = getOutputGeneratorByClassnameAndVariant(outputGeneratorClassName, outputGeneratorVariant);
LicenseInfoFile licenseInfoFile = new LicenseInfoFile();

licenseInfoFile.setOutputFormatInfo(generator.getOutputFormatInfo());
Expand All @@ -115,7 +123,7 @@ public LicenseInfoFile getLicenseInfoFile(Project project, User user, String out
} else if (output instanceof String) {
licenseInfoFile.setGeneratedOutput(((String) output).getBytes());
} else {
throw new TException("Unsupported output generator result: " + output.getClass().getName());
throw new TException("Unsupported output generator result: " + output.getClass().getSimpleName());
}

return licenseInfoFile;
Expand Down Expand Up @@ -279,7 +287,17 @@ protected List<LicenseInfoParsingResult> assignReleaseToLicenseInfoParsingResult

protected OutputGenerator<?> getOutputGeneratorByClassname(String generatorClassname) throws TException {
assertNotNull(generatorClassname);
return outputGenerators.stream().filter(outputGenerator -> generatorClassname.equals(outputGenerator.getClass().getName()))
return outputGenerators.stream()
.filter(outputGenerator -> generatorClassname.equals(outputGenerator.getClass().getSimpleName()))
.findFirst().orElseThrow(() -> new TException("Unknown output generator: " + generatorClassname));
}

protected OutputGenerator<?> getOutputGeneratorByClassnameAndVariant(String generatorClassname, OutputFormatVariant generatorVariant) throws TException {
assertNotNull(generatorClassname);
assertNotNull(generatorVariant);
return outputGenerators.stream()
.filter(outputGenerator -> generatorClassname.equals(outputGenerator.getClass().getSimpleName()))
.filter(outputGenerator -> generatorVariant.equals(outputGenerator.getOutputVariant()))
.findFirst().orElseThrow(() -> new TException("Unknown output generator: " + generatorClassname));
}

Expand Down
Expand Up @@ -10,18 +10,19 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/

package org.eclipse.sw360.licenseinfo.outputGenerators;

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.thrift.TException;
import org.apache.xmlbeans.XmlException;
import org.eclipse.sw360.datahandler.thrift.SW360Exception;
import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseInfo;
import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseInfoParsingResult;
import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseInfoRequestStatus;
import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseNameWithText;
import org.eclipse.sw360.datahandler.thrift.ThriftClients;
import org.eclipse.sw360.datahandler.thrift.licenseinfo.*;
import org.eclipse.sw360.datahandler.thrift.licenses.License;
import org.eclipse.sw360.datahandler.thrift.licenses.LicenseService;
import org.eclipse.sw360.datahandler.thrift.licenses.Todo;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
Expand All @@ -34,35 +35,50 @@ public class DocxGenerator extends OutputGenerator<byte[]> {

private static final String UNKNOWN_LICENSE_NAME = "Unknown license name";
private static final String UNKNOWN_FILE_NAME = "Unknown file name";
private static final String TODO_DEFAULT_TEXT = "todo not determined so far.";

private static final String DOCX_TEMPLATE_FILE = "/templateFrontpageContent.docx";
private static final String DOCX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
private static final String DOCX_OUTPUT_TYPE = "docx";

public DocxGenerator() {
super("docx", "License information as DOCX", true, "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
public DocxGenerator(OutputFormatVariant outputFormatVariant, String description) {
super(DOCX_OUTPUT_TYPE, description, true, DOCX_MIME_TYPE, outputFormatVariant);
}

@Override
public byte[] generateOutputFile(Collection<LicenseInfoParsingResult> projectLicenseInfoResults, String projectName, String projectVersion, String licenseInfoHeaderText) throws SW360Exception {
ByteArrayOutputStream docxOutputStream = new ByteArrayOutputStream();
try {
XWPFDocument document = new XWPFDocument(this.getClass().getResourceAsStream("/templateFrontpageContent.docx"));
fillDocument(document, projectLicenseInfoResults, projectName, projectVersion, licenseInfoHeaderText);
ByteArrayOutputStream docxOutputStream = new ByteArrayOutputStream();
document.write(docxOutputStream);
XWPFDocument xwpfDocument = new XWPFDocument(this.getClass().getResourceAsStream(DOCX_TEMPLATE_FILE));
switch (getOutputVariant()) {
case DISCLOSURE:
fillDocument(xwpfDocument, projectLicenseInfoResults, projectName, projectVersion, licenseInfoHeaderText, false);
break;
case REPORT:
fillDocument(xwpfDocument, projectLicenseInfoResults, projectName, projectVersion, licenseInfoHeaderText, true);
break;
default:
throw new IllegalArgumentException("Unknown generator variant type: " + getOutputVariant());
}
xwpfDocument.write(docxOutputStream);
docxOutputStream.close();
return docxOutputStream.toByteArray();
} catch (XmlException e) {
throw new SW360Exception("Got XmlException while generating docx document: " + e.getMessage());
} catch (IOException ioe) {
throw new SW360Exception("Got IOException when generating docx document: " + ioe.getMessage());
} catch (IOException e) {
throw new SW360Exception("Got IOException when generating docx document: " + e.getMessage());
} catch (TException e) {
throw new SW360Exception("Error reading sw360 licenses: " + e.getMessage());
}
return docxOutputStream.toByteArray();
}

private void fillDocument(XWPFDocument document, Collection<LicenseInfoParsingResult> projectLicenseInfoResults,
String projectName, String projectVersion, String licenseInfoHeaderText) throws XmlException {
String projectName, String projectVersion, String licenseInfoHeaderText, boolean includeObligations) throws XmlException, TException {
replaceText(document, "$license-info-header", licenseInfoHeaderText);
replaceText(document, "$project-name", projectName);
replaceText(document, "$project-version", projectVersion);

fillReleaseBulletList(document, projectLicenseInfoResults);
fillReleaseDetailList(document, projectLicenseInfoResults);
fillReleaseDetailList(document, projectLicenseInfoResults, includeObligations);
fillLicenseList(document, projectLicenseInfoResults);
}

Expand All @@ -75,32 +91,17 @@ private void fillReleaseBulletList(XWPFDocument document, Collection<LicenseInfo
addPageBreak(document);
}

private void fillReleaseDetailList(XWPFDocument document, Collection<LicenseInfoParsingResult> projectLicenseInfoResults) {
XWPFRun releaseTitleTextRun = document.createParagraph().createRun();
addFormattedText(releaseTitleTextRun, "Detailed Releases Information", FONT_SIZE + 2, true);
XWPFRun releaseInfoTextRun = document.createParagraph().createRun();
setText(releaseInfoTextRun, "Please note the following license conditions and copyright " +
private void fillReleaseDetailList(XWPFDocument document, Collection<LicenseInfoParsingResult> projectLicenseInfoResults, boolean includeObligations) throws TException {
addFormattedText(document.createParagraph().createRun(), "Detailed Releases Information", FONT_SIZE + 2, true);
setText(document.createParagraph().createRun(), "Please note the following license conditions and copyright " +
"notices applicable to Open Source Software and/or other components (or parts thereof):");
addNewLines(document, 0);

for (LicenseInfoParsingResult parsingResult : projectLicenseInfoResults) {
addReleaseTitle(document, parsingResult);
if (parsingResult.getStatus() == LicenseInfoRequestStatus.SUCCESS) {
XWPFRun copyrightTitleRun = document.createParagraph().createRun();
addFormattedText(copyrightTitleRun, "Copyrights", FONT_SIZE, true);
for (String copyright : getReleaseCopyrights(parsingResult)) {
XWPFParagraph copyPara = document.createParagraph();
copyPara.setSpacingAfter(0);
setText(copyPara.createRun(), copyright);
}
XWPFRun licensesTitleRun = document.createParagraph().createRun();
addNewLines(licensesTitleRun, 1);
addFormattedText(licensesTitleRun, "Licenses", FONT_SIZE, true);
for (String licenseName : getReleasesLicenses(parsingResult)) {
XWPFParagraph licensePara = document.createParagraph();
licensePara.setSpacingAfter(0);
addBookmarkHyperLink(licensePara, licenseName, licenseName);
}
addCopyrights(document, parsingResult);
addLicenses(document, parsingResult, includeObligations);
} else {
XWPFRun errorRun = document.createParagraph().createRun();
String errorText = nullToEmptyString(parsingResult.getMessage());
Expand All @@ -121,6 +122,45 @@ private void addReleaseTitle(XWPFDocument document, LicenseInfoParsingResult par
addNewLines(document, 0);
}

private void addCopyrights(XWPFDocument document, LicenseInfoParsingResult parsingResult) {
XWPFRun copyrightTitleRun = document.createParagraph().createRun();
addFormattedText(copyrightTitleRun, "Copyrights", FONT_SIZE, true);
for (String copyright : getReleaseCopyrights(parsingResult)) {
XWPFParagraph copyPara = document.createParagraph();
copyPara.setSpacingAfter(0);
setText(copyPara.createRun(), copyright);
}
}

private void addLicenses(XWPFDocument document, LicenseInfoParsingResult parsingResult, boolean includeObligations) throws TException {
XWPFRun licensesTitleRun = document.createParagraph().createRun();
addNewLines(licensesTitleRun, 1);
addFormattedText(licensesTitleRun, "Licenses", FONT_SIZE, true);
for (String licenseName : getReleasesLicenses(parsingResult)) {
XWPFParagraph licensePara = document.createParagraph();
licensePara.setSpacingAfter(0);
addBookmarkHyperLink(licensePara, licenseName, licenseName);
if (includeObligations) {
addLicenseObligations(document, licenseName);
}
}
}

private void addLicenseObligations(XWPFDocument document, String spdxLicense) throws TException {
List<License> sw360Licenses = getLicenses();
XWPFRun todoTitleRun = document.createParagraph().createRun();
addNewLines(todoTitleRun, 0);
Set<String> todos = getTodosFromLicenses(spdxLicense, sw360Licenses);
addFormattedText(todoTitleRun, "Obligations for license " + spdxLicense + ":", FONT_SIZE, true);
for (String todo : todos) {
XWPFParagraph copyPara = document.createParagraph();
copyPara.setSpacingAfter(0);
XWPFRun todoRun = copyPara.createRun();
setText(todoRun, todo);
addNewLines(todoRun, 1);
}
}

private Set<String> getReleaseCopyrights(LicenseInfoParsingResult licenseInfoParsingResult) {
Set<String> copyrights = Collections.emptySet();
if (licenseInfoParsingResult.isSetLicenseInfo()) {
Expand Down Expand Up @@ -154,6 +194,28 @@ private String getFilename(LicenseInfoParsingResult licenseInfoParsingResult) {
.orElse(UNKNOWN_FILE_NAME);
}

private static Set<String> getTodosFromLicenses(String spdxLicense, List<License> licenses) {
Set<String> todos = new HashSet<>();
if (spdxLicense != null && !spdxLicense.isEmpty() && licenses != null) {
for (License license : licenses) {
if (spdxLicense.equalsIgnoreCase(license.getId())) {
for (Todo todo : license.getTodos()) {
todos.add(todo.getText());
}
}
}
if (todos.isEmpty()) {
todos.add(TODO_DEFAULT_TEXT);
}
}
return todos;
}

private static List<License> getLicenses() throws TException {
LicenseService.Iface licenseClient = new ThriftClients().makeLicenseClient();
return licenseClient.getLicenses();
}

private void fillLicenseList(XWPFDocument document, Collection<LicenseInfoParsingResult> projectLicenseInfoResults) {
List<LicenseNameWithText> licenseNameWithTexts = OutputGenerator.getSortedLicenseNameWithTexts(projectLicenseInfoResults);
XWPFRun licenseHeaderRun = document.createParagraph().createRun();
Expand All @@ -165,6 +227,7 @@ private void fillLicenseList(XWPFDocument document, Collection<LicenseInfoParsin
licenseParagraph.setStyle(STYLE_HEADING);
String licenseName = licenseNameWithText.isSetLicenseName() ? licenseNameWithText.getLicenseName() : UNKNOWN_LICENSE_NAME;
addBookmark(licenseParagraph, licenseName, licenseName);
addNewLines(document, 0);
setText(document.createParagraph().createRun(), nullToEmptyString(licenseNameWithText.getLicenseText()));
addNewLines(document, 1);
}
Expand Down
Expand Up @@ -24,7 +24,7 @@

public class DocxUtils {

public static final int FONT_SIZE = 12;
public static final int FONT_SIZE = 10;
public static final String ALERT_COLOR = "e95850";
public static final String FONT_FAMILY = "Calibri";
public static final String STYLE_HEADING = "Heading2";
Expand Down

0 comments on commit eb71cf2

Please sign in to comment.