org.codehaus.mojo.license.extended.spreadsheet.ExcelFileWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of license-maven-plugin Show documentation
Show all versions of license-maven-plugin Show documentation
Maven plugin to download and collect license files from project dependencies.
The newest version!
package org.codehaus.mojo.license.extended.spreadsheet;
/*
* #%L
* License Maven Plugin
* %%
* Copyright (C) 2019 Jan-Hendrik Diederich
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.maven.model.Developer;
import org.apache.maven.model.Organization;
import org.apache.maven.model.Scm;
import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.ss.util.WorkbookUtil;
import org.apache.poi.xssf.usermodel.IndexedColorMap;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.codehaus.mojo.license.download.ProjectLicense;
import org.codehaus.mojo.license.download.ProjectLicenseInfo;
import org.codehaus.mojo.license.extended.ExtendedInfo;
import org.codehaus.mojo.license.extended.InfoFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.GAP_WIDTH;
import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.getDownloadColumn;
/**
* Writes project license infos into Excel file.
*/
public class ExcelFileWriter {
private static final BorderStyle HEADER_CELLS_BORDER_STYLE = BorderStyle.MEDIUM;
private static final Logger LOG = LoggerFactory.getLogger(ExcelFileWriter.class);
private ExcelFileWriter() {}
/**
* Writes a list of projects into Excel file.
*
* @param projectLicenseInfos Project license infos to write.
* @param licensesExcelOutputFile Excel output file in latest format (OOXML).
*/
public static void write(List projectLicenseInfos, final File licensesExcelOutputFile) {
if (CollectionUtils.isEmpty(projectLicenseInfos)) {
LOG.debug("Nothing to write to excel, no project data.");
return;
}
LOG.debug("Write Microsoft Excel file {}", licensesExcelOutputFile);
final XSSFWorkbook wb = new XSSFWorkbook();
final Sheet sheet = wb.createSheet(WorkbookUtil.createSafeSheetName(SpreadsheetUtil.TABLE_NAME));
final IndexedColorMap colorMap = wb.getStylesSource().getIndexedColors();
final XSSFColor alternatingRowsColor = new XSSFColor(
new byte[] {
(byte) SpreadsheetUtil.ALTERNATING_ROWS_COLOR[0],
(byte) SpreadsheetUtil.ALTERNATING_ROWS_COLOR[1],
(byte) SpreadsheetUtil.ALTERNATING_ROWS_COLOR[2]
},
colorMap);
createHeader(projectLicenseInfos, wb, sheet);
writeData(projectLicenseInfos, wb, sheet, alternatingRowsColor);
try (OutputStream fileOut = Files.newOutputStream(licensesExcelOutputFile.toPath())) {
wb.write(fileOut);
LOG.debug("Written Microsoft Excel file {}", licensesExcelOutputFile);
} catch (IOException e) {
LOG.error("Error on storing Microsoft Excel file with license and other information", e);
}
}
@SuppressWarnings("checkstyle:MethodLength")
private static void createHeader(List projectLicenseInfos, Workbook wb, Sheet sheet) {
boolean hasExtendedInfo = false;
for (ProjectLicenseInfo projectLicenseInfo : projectLicenseInfos) {
if (projectLicenseInfo.getExtendedInfo() != null) {
hasExtendedInfo = true;
break;
}
}
// Create header style
CellStyle headerCellStyle = wb.createCellStyle();
headerCellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());
headerCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
Font headerFont = wb.createFont();
headerFont.setBold(true);
headerCellStyle.setFont(headerFont);
headerCellStyle.setAlignment(HorizontalAlignment.CENTER);
setBorderStyle(headerCellStyle, HEADER_CELLS_BORDER_STYLE);
// Create 1st header row. The Maven/JAR header row
Row mavenJarRow = sheet.createRow(0);
// Create Maven header cell
createMergedCellsInRow(
sheet,
SpreadsheetUtil.MAVEN_START_COLUMN,
SpreadsheetUtil.MAVEN_END_COLUMN,
headerCellStyle,
mavenJarRow,
"Maven information",
0);
if (hasExtendedInfo) {
// Create JAR header cell
createMergedCellsInRow(
sheet,
SpreadsheetUtil.EXTENDED_INFO_START_COLUMN,
SpreadsheetUtil.EXTENDED_INFO_END_COLUMN,
headerCellStyle,
mavenJarRow,
"JAR Content",
0);
}
// Create 2nd header row
Row secondHeaderRow = sheet.createRow(1);
// Create Maven "General" header
createMergedCellsInRow(
sheet,
SpreadsheetUtil.GENERAL_START_COLUMN,
SpreadsheetUtil.GENERAL_END_COLUMN,
headerCellStyle,
secondHeaderRow,
"General",
1);
// Create Maven "Plugin ID" header
createMergedCellsInRow(
sheet,
SpreadsheetUtil.PLUGIN_ID_START_COLUMN,
SpreadsheetUtil.PLUGIN_ID_END_COLUMN,
headerCellStyle,
secondHeaderRow,
"Plugin ID",
1);
// Gap "General" <-> "Plugin ID".
sheet.setColumnWidth(SpreadsheetUtil.GENERAL_END_COLUMN, SpreadsheetUtil.GAP_WIDTH);
// Create Maven "Licenses" header
createMergedCellsInRow(
sheet,
SpreadsheetUtil.LICENSES_START_COLUMN,
SpreadsheetUtil.LICENSES_END_COLUMN,
headerCellStyle,
secondHeaderRow,
"Licenses",
1);
// Gap "Plugin ID" <-> "Licenses".
sheet.setColumnWidth(SpreadsheetUtil.PLUGIN_ID_END_COLUMN, SpreadsheetUtil.GAP_WIDTH);
// Create Maven "Developers" header
createMergedCellsInRow(
sheet,
SpreadsheetUtil.DEVELOPERS_START_COLUMN,
SpreadsheetUtil.DEVELOPERS_END_COLUMN,
headerCellStyle,
secondHeaderRow,
"Developers",
1);
// Gap "Licenses" <-> "Developers".
sheet.setColumnWidth(SpreadsheetUtil.LICENSES_END_COLUMN, SpreadsheetUtil.GAP_WIDTH);
// Create Maven "Miscellaneous" header
createMergedCellsInRow(
sheet,
SpreadsheetUtil.MISC_START_COLUMN,
SpreadsheetUtil.MISC_END_COLUMN,
headerCellStyle,
secondHeaderRow,
"Miscellaneous",
1);
// Gap "Developers" <-> "Miscellaneous".
sheet.setColumnWidth(SpreadsheetUtil.DEVELOPERS_END_COLUMN, SpreadsheetUtil.GAP_WIDTH);
if (hasExtendedInfo) {
createMergedCellsInRow(
sheet,
SpreadsheetUtil.MANIFEST_START_COLUMN,
SpreadsheetUtil.MANIFEST_END_COLUMN,
headerCellStyle,
secondHeaderRow,
"MANIFEST.MF",
1);
// Gap "Miscellaneous" <-> "MANIFEST.MF".
sheet.setColumnWidth(SpreadsheetUtil.DEVELOPERS_END_COLUMN, SpreadsheetUtil.GAP_WIDTH);
createMergedCellsInRow(
sheet,
SpreadsheetUtil.INFO_NOTICES_START_COLUMN,
SpreadsheetUtil.INFO_NOTICES_END_COLUMN,
headerCellStyle,
secondHeaderRow,
"Notices text files",
1);
// Gap "MANIFEST.MF" <-> "Notice text files".
sheet.setColumnWidth(SpreadsheetUtil.MANIFEST_END_COLUMN, SpreadsheetUtil.GAP_WIDTH);
createMergedCellsInRow(
sheet,
SpreadsheetUtil.INFO_LICENSES_START_COLUMN,
SpreadsheetUtil.INFO_LICENSES_END_COLUMN,
headerCellStyle,
secondHeaderRow,
"License text files",
1);
// Gap "Notice text files" <-> "License text files".
sheet.setColumnWidth(SpreadsheetUtil.INFO_NOTICES_END_COLUMN, SpreadsheetUtil.GAP_WIDTH);
createMergedCellsInRow(
sheet,
SpreadsheetUtil.INFO_SPDX_START_COLUMN,
SpreadsheetUtil.INFO_SPDX_END_COLUMN,
headerCellStyle,
secondHeaderRow,
"SPDX license id matched",
1);
// Gap "License text files" <-> "SPDX license matches".
sheet.setColumnWidth(SpreadsheetUtil.INFO_LICENSES_END_COLUMN, SpreadsheetUtil.GAP_WIDTH);
}
// sheet.setColumnGroupCollapsed();
sheet.setColumnWidth(getDownloadColumn(hasExtendedInfo) - 1, GAP_WIDTH);
// Create 3rd header row
Row thirdHeaderRow = sheet.createRow(2);
// General
createCellsInRow(thirdHeaderRow, SpreadsheetUtil.GENERAL_START_COLUMN, headerCellStyle, "Name");
// Plugin ID
createCellsInRow(
thirdHeaderRow,
SpreadsheetUtil.PLUGIN_ID_START_COLUMN,
headerCellStyle,
"Group ID",
"Artifact ID",
"Version");
// Licenses
createCellsInRow(
thirdHeaderRow,
SpreadsheetUtil.LICENSES_START_COLUMN,
headerCellStyle,
"Name",
"URL",
"Distribution",
"Comments",
"File");
// Developers
createCellsInRow(
thirdHeaderRow,
SpreadsheetUtil.DEVELOPERS_START_COLUMN,
headerCellStyle,
"Id",
"Email",
"Name",
"Organization",
"Organization URL",
"URL",
"Timezone");
// Miscellaneous
createCellsInRow(
thirdHeaderRow,
SpreadsheetUtil.MISC_START_COLUMN,
headerCellStyle,
"Inception Year",
"Organization",
"SCM",
"URL");
int headerLineCount = 3;
if (hasExtendedInfo) {
// MANIFEST.MF
createCellsInRow(
thirdHeaderRow,
SpreadsheetUtil.MANIFEST_START_COLUMN,
headerCellStyle,
"Bundle license",
"Bundle vendor",
"Implementation vendor");
// 3 InfoFile groups: Notices, Licenses and SPDX-Licenses.
createInfoFileCellsInRow(
thirdHeaderRow,
headerCellStyle,
SpreadsheetUtil.INFO_NOTICES_START_COLUMN,
SpreadsheetUtil.INFO_LICENSES_START_COLUMN,
SpreadsheetUtil.INFO_SPDX_START_COLUMN);
sheet.createFreezePane(getDownloadColumn(true) - 1, headerLineCount);
} else {
sheet.createFreezePane(getDownloadColumn(false) - 1, headerLineCount);
}
sheet.createFreezePane(SpreadsheetUtil.GENERAL_END_COLUMN, headerLineCount);
}
/* Possible improvement:
Clean this method up.
Reduce parameters, complicated parameters/DTO pattern.
But keep it still threadsafe. */
@SuppressWarnings("checkstyle:MethodLength")
private static void writeData(
List projectLicenseInfos,
XSSFWorkbook wb,
Sheet sheet,
XSSFColor alternatingRowsColor) {
final int firstRowIndex = 3;
int currentRowIndex = firstRowIndex;
final Map rowMap = new HashMap<>();
boolean hasExtendedInfo = false;
final CellStyle hyperlinkStyleNormal = createHyperlinkStyle(wb, null);
final CellStyle hyperlinkStyleGray = createHyperlinkStyle(wb, alternatingRowsColor);
boolean grayBackground = false;
XSSFCellStyle styleGray = wb.createCellStyle();
styleGray.setFillForegroundColor(alternatingRowsColor);
styleGray.setFillPattern(FillPatternType.SOLID_FOREGROUND);
for (ProjectLicenseInfo projectInfo : projectLicenseInfos) {
final CellStyle cellStyle, hyperlinkStyle;
LOG.debug("Writing {}:{} into Microsoft Excel file", projectInfo.getGroupId(), projectInfo.getArtifactId());
if (grayBackground) {
cellStyle = styleGray;
hyperlinkStyle = hyperlinkStyleGray;
} else {
cellStyle = null;
hyperlinkStyle = hyperlinkStyleNormal;
}
grayBackground = !grayBackground;
int extraRows = 0;
Row currentRow = sheet.createRow(currentRowIndex);
rowMap.put(currentRowIndex, currentRow);
// Plugin ID
createDataCellsInRow(
currentRow,
SpreadsheetUtil.PLUGIN_ID_START_COLUMN,
cellStyle,
projectInfo.getGroupId(),
projectInfo.getArtifactId(),
projectInfo.getVersion());
// Licenses
final CellListParameter cellListParameter = new CellListParameter(sheet, rowMap, cellStyle);
SpreadsheetUtil.CurrentRowData currentRowData =
new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo);
extraRows = addList(
cellListParameter,
currentRowData,
SpreadsheetUtil.LICENSES_START_COLUMN,
SpreadsheetUtil.LICENSES_COLUMNS,
projectInfo.getLicenses(),
(Row licenseRow, ProjectLicense license) -> {
Cell[] licenses = createDataCellsInRow(
licenseRow,
SpreadsheetUtil.LICENSES_START_COLUMN,
cellStyle,
license.getName(),
license.getUrl(),
license.getDistribution(),
license.getComments(),
license.getFile());
addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.URL);
});
final ExtendedInfo extendedInfo = projectInfo.getExtendedInfo();
if (extendedInfo != null) {
hasExtendedInfo = true;
// General
createDataCellsInRow(
currentRow, SpreadsheetUtil.GENERAL_START_COLUMN, cellStyle, extendedInfo.getName());
// Developers
currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo);
extraRows = addList(
cellListParameter,
currentRowData,
SpreadsheetUtil.DEVELOPERS_START_COLUMN,
SpreadsheetUtil.DEVELOPERS_COLUMNS,
extendedInfo.getDevelopers(),
(Row developerRow, Developer developer) -> {
Cell[] licenses = createDataCellsInRow(
developerRow,
SpreadsheetUtil.DEVELOPERS_START_COLUMN,
cellStyle,
developer.getId(),
developer.getEmail(),
developer.getName(),
developer.getOrganization(),
developer.getOrganizationUrl(),
developer.getUrl(),
developer.getTimezone());
addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.EMAIL);
addHyperlinkIfExists(wb, licenses[4], hyperlinkStyle, HyperlinkType.URL);
addHyperlinkIfExists(wb, licenses[5], hyperlinkStyle, HyperlinkType.URL);
});
// Miscellaneous
Cell[] miscCells = createDataCellsInRow(
currentRow,
SpreadsheetUtil.MISC_START_COLUMN,
cellStyle,
extendedInfo.getInceptionYear(),
Optional.ofNullable(extendedInfo.getOrganization())
.map(Organization::getName)
.orElse(null),
Optional.ofNullable(extendedInfo.getScm())
.map(Scm::getUrl)
.orElse(null),
extendedInfo.getUrl());
addHyperlinkIfExists(wb, miscCells[2], hyperlinkStyle, HyperlinkType.URL);
addHyperlinkIfExists(wb, miscCells[3], hyperlinkStyle, HyperlinkType.URL);
// MANIFEST.MF
createDataCellsInRow(
currentRow,
SpreadsheetUtil.MANIFEST_START_COLUMN,
cellStyle,
extendedInfo.getBundleLicense(),
extendedInfo.getBundleVendor(),
extendedInfo.getImplementationVendor());
// Info files
if (!CollectionUtils.isEmpty(extendedInfo.getInfoFiles())) {
// Sort all info files by type into 3 different lists, each list for each of the 3 types.
List notices = new ArrayList<>();
List licenses = new ArrayList<>();
List spdxs = new ArrayList<>();
extendedInfo.getInfoFiles().forEach(infoFile -> {
switch (infoFile.getType()) {
case LICENSE:
licenses.add(infoFile);
break;
case NOTICE:
notices.add(infoFile);
break;
case SPDX_LICENSE:
spdxs.add(infoFile);
break;
default:
break;
}
});
// InfoFile notices text file
currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo);
extraRows = addInfoFileList(
cellListParameter,
currentRowData,
SpreadsheetUtil.INFO_NOTICES_START_COLUMN,
SpreadsheetUtil.INFO_NOTICES_COLUMNS,
notices);
// InfoFile licenses text file
currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo);
extraRows = addInfoFileList(
cellListParameter,
currentRowData,
SpreadsheetUtil.INFO_LICENSES_START_COLUMN,
SpreadsheetUtil.INFO_LICENSES_COLUMNS,
licenses);
// InfoFile spdx licenses text file
currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo);
extraRows = addInfoFileList(
cellListParameter,
currentRowData,
SpreadsheetUtil.INFO_SPDX_START_COLUMN,
SpreadsheetUtil.INFO_SPDX_COLUMNS,
spdxs);
} else if (cellListParameter.cellStyle != null) {
setStyleOnEmptyCells(
cellListParameter,
currentRowData,
SpreadsheetUtil.INFO_NOTICES_START_COLUMN,
SpreadsheetUtil.INFO_NOTICES_COLUMNS);
setStyleOnEmptyCells(
cellListParameter,
currentRowData,
SpreadsheetUtil.INFO_LICENSES_START_COLUMN,
SpreadsheetUtil.INFO_LICENSES_COLUMNS);
setStyleOnEmptyCells(
cellListParameter,
currentRowData,
SpreadsheetUtil.INFO_SPDX_START_COLUMN,
SpreadsheetUtil.INFO_SPDX_COLUMNS);
}
}
if (CollectionUtils.isNotEmpty(projectInfo.getDownloaderMessages())) {
currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo);
int startColumn = hasExtendedInfo
? SpreadsheetUtil.DOWNLOAD_MESSAGE_EXTENDED_COLUMN
: SpreadsheetUtil.DOWNLOAD_MESSAGE_NOT_EXTENDED_COLUMN;
extraRows = addList(
cellListParameter,
currentRowData,
startColumn,
SpreadsheetUtil.DOWNLOAD_MESSAGE_COLUMNS,
projectInfo.getDownloaderMessages(),
(Row licenseRow, String message) -> {
Cell[] licenses = createDataCellsInRow(licenseRow, startColumn, cellStyle, message);
if (message.matches(SpreadsheetUtil.VALID_LINK)) {
addHyperlinkIfExists(wb, licenses[0], hyperlinkStyle, HyperlinkType.URL);
}
});
}
currentRowIndex += extraRows + 1;
}
autosizeColumns(sheet, hasExtendedInfo);
}
private static CellStyle createHyperlinkStyle(XSSFWorkbook wb, XSSFColor backgroundColor) {
Font hyperlinkFont = wb.createFont();
hyperlinkFont.setUnderline(Font.U_SINGLE);
hyperlinkFont.setColor(IndexedColors.BLUE.getIndex());
XSSFCellStyle hyperlinkStyle = wb.createCellStyle();
if (backgroundColor != null) {
hyperlinkStyle.setFillForegroundColor(backgroundColor);
hyperlinkStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
}
hyperlinkStyle.setFont(hyperlinkFont);
return hyperlinkStyle;
}
private static void autosizeColumns(Sheet sheet, boolean hasExtendedInfo) {
autosizeColumns(
sheet,
new ImmutablePair<>(SpreadsheetUtil.GENERAL_START_COLUMN, SpreadsheetUtil.GENERAL_END_COLUMN),
new ImmutablePair<>(SpreadsheetUtil.PLUGIN_ID_START_COLUMN, SpreadsheetUtil.PLUGIN_ID_END_COLUMN),
new ImmutablePair<>(SpreadsheetUtil.LICENSES_START_COLUMN, SpreadsheetUtil.LICENSES_END_COLUMN),
new ImmutablePair<>(SpreadsheetUtil.DEVELOPERS_START_COLUMN, SpreadsheetUtil.DEVELOPERS_END_COLUMN - 1),
new ImmutablePair<>(SpreadsheetUtil.MISC_START_COLUMN + 1, SpreadsheetUtil.MISC_END_COLUMN));
// The column header widths are most likely wider than the actual cells content.
sheet.setColumnWidth(SpreadsheetUtil.DEVELOPERS_END_COLUMN - 1, SpreadsheetUtil.TIMEZONE_WIDTH);
sheet.setColumnWidth(SpreadsheetUtil.MISC_START_COLUMN, SpreadsheetUtil.INCEPTION_YEAR_WIDTH);
if (hasExtendedInfo) {
autosizeColumns(
sheet,
new ImmutablePair<>(SpreadsheetUtil.MANIFEST_START_COLUMN, SpreadsheetUtil.MANIFEST_END_COLUMN),
new ImmutablePair<>(
SpreadsheetUtil.INFO_NOTICES_START_COLUMN + 2, SpreadsheetUtil.INFO_NOTICES_END_COLUMN),
new ImmutablePair<>(
SpreadsheetUtil.INFO_LICENSES_START_COLUMN + 2, SpreadsheetUtil.INFO_LICENSES_END_COLUMN),
new ImmutablePair<>(
SpreadsheetUtil.INFO_SPDX_START_COLUMN + 2, SpreadsheetUtil.INFO_SPDX_END_COLUMN));
}
autosizeColumns(
sheet,
new ImmutablePair<>(
getDownloadColumn(hasExtendedInfo),
getDownloadColumn(hasExtendedInfo) + SpreadsheetUtil.DOWNLOAD_MESSAGE_COLUMNS));
}
@SafeVarargs
private static void autosizeColumns(Sheet sheet, Pair... ranges) {
for (Pair range : ranges) {
for (int i = range.getLeft(); i < range.getRight(); i++) {
sheet.autoSizeColumn(i);
}
}
}
private static int addInfoFileList(
CellListParameter cellListParameter,
SpreadsheetUtil.CurrentRowData currentRowData,
int startColumn,
int columnsToFill,
List infoFiles) {
return addList(
cellListParameter,
currentRowData,
startColumn,
columnsToFill,
infoFiles,
(Row infoFileRow, InfoFile infoFile) -> {
final String copyrightLines = Optional.ofNullable(infoFile.getExtractedCopyrightLines())
.map(strings -> String.join(SpreadsheetUtil.COPYRIGHT_JOIN_SEPARATOR, strings))
.orElse(null);
createDataCellsInRow(
infoFileRow,
startColumn,
cellListParameter.getCellStyle(),
infoFile.getContent(),
copyrightLines,
infoFile.getFileName());
});
}
private static int addList(
CellListParameter cellListParameter,
SpreadsheetUtil.CurrentRowData currentRowData,
int startColumn,
int columnsToFill,
List list,
BiConsumer biConsumer) {
if (!CollectionUtils.isEmpty(list)) {
for (int i = 0; i < list.size(); i++) {
T type = list.get(i);
Integer index = currentRowData.getCurrentRowIndex() + i;
Row row = cellListParameter.getRows().get(index);
if (row == null) {
row = cellListParameter.getSheet().createRow(index);
cellListParameter.getRows().put(index, row);
if (cellListParameter.getCellStyle() != null) {
// Style all empty left cells, in the columns left from this
createAndStyleCells(
row,
cellListParameter.getCellStyle(),
new ImmutablePair<>(
SpreadsheetUtil.GENERAL_START_COLUMN, SpreadsheetUtil.GENERAL_END_COLUMN),
new ImmutablePair<>(
SpreadsheetUtil.PLUGIN_ID_START_COLUMN, SpreadsheetUtil.PLUGIN_ID_END_COLUMN),
new ImmutablePair<>(
SpreadsheetUtil.LICENSES_START_COLUMN, SpreadsheetUtil.LICENSES_END_COLUMN));
if (currentRowData.isHasExtendedInfo()) {
createAndStyleCells(
row,
cellListParameter.getCellStyle(),
new ImmutablePair<>(
SpreadsheetUtil.DEVELOPERS_START_COLUMN,
SpreadsheetUtil.DEVELOPERS_END_COLUMN),
new ImmutablePair<>(
SpreadsheetUtil.MISC_START_COLUMN, SpreadsheetUtil.MISC_END_COLUMN),
// JAR
new ImmutablePair<>(
SpreadsheetUtil.MANIFEST_START_COLUMN, SpreadsheetUtil.MANIFEST_END_COLUMN),
new ImmutablePair<>(
SpreadsheetUtil.INFO_LICENSES_START_COLUMN,
SpreadsheetUtil.INFO_LICENSES_END_COLUMN),
new ImmutablePair<>(
SpreadsheetUtil.INFO_NOTICES_START_COLUMN,
SpreadsheetUtil.INFO_NOTICES_END_COLUMN),
new ImmutablePair<>(
SpreadsheetUtil.INFO_SPDX_START_COLUMN,
SpreadsheetUtil.INFO_SPDX_END_COLUMN));
}
}
currentRowData.setExtraRows(currentRowData.getExtraRows() + 1);
}
biConsumer.accept(row, type);
}
} else if (cellListParameter.cellStyle != null) {
setStyleOnEmptyCells(cellListParameter, currentRowData, startColumn, columnsToFill);
}
return currentRowData.getExtraRows();
}
/**
* If no cells are set, color at least the background,
* to color concatenated blocks with the same background color.
*
* @param cellListParameter Passes data about sheet, row, cell style.
* @param currentRowData Passes data about the current indices for rows and columns.
* @param startColumn Column where to start setting the style.
* @param columnsToFill How many columns to set the style on, starting from 'startColumn'.
*/
private static void setStyleOnEmptyCells(
CellListParameter cellListParameter,
SpreadsheetUtil.CurrentRowData currentRowData,
int startColumn,
int columnsToFill) {
Row row = cellListParameter.getRows().get(currentRowData.getCurrentRowIndex());
for (int i = 0; i < columnsToFill; i++) {
Cell cell = row.createCell(startColumn + i, CellType.STRING);
cell.setCellStyle(cellListParameter.getCellStyle());
}
}
@SafeVarargs
private static void createAndStyleCells(Row row, CellStyle cellStyle, Pair... ranges) {
for (Pair range : ranges) {
for (int i = range.getLeft(); i < range.getRight(); i++) {
Cell cell = row.createCell(i, CellType.STRING);
cell.setCellStyle(cellStyle);
}
}
}
private static void addHyperlinkIfExists(
Workbook workbook, Cell cell, CellStyle hyperlinkStyle, HyperlinkType hyperlinkType) {
final String link = cell.getStringCellValue();
if (!StringUtils.isEmpty(link)) {
Hyperlink hyperlink = workbook.getCreationHelper().createHyperlink(hyperlinkType);
final String modifiedLink = prefixedHyperlink(hyperlinkType, link);
try {
hyperlink.setAddress(modifiedLink);
cell.setHyperlink(hyperlink);
cell.setCellStyle(hyperlinkStyle);
} catch (IllegalArgumentException e) {
LOG.debug(
"Can't set Hyperlink for cell value " + link + " (" + modifiedLink
+ ") it gets rejected as URI",
e);
}
}
}
/**
* Adds "https://" prefix to link if it's missing.
*
* @param hyperlinkType Type of hyperlink.
* @param link Hyperlink address.
* @return Prefixed hyperlink.
*/
private static String prefixedHyperlink(HyperlinkType hyperlinkType, String link) {
final String modifiedLink;
link = link.trim().replace(" dot ", ".");
if (hyperlinkType == HyperlinkType.EMAIL) {
// Replace all "bla com" with "bla.com".
link = link.replace(" at ", "@");
if (link.contains("@") && link.matches(".*\\s[a-zA-Z]{2,3}$")) {
modifiedLink = link.replace(" ", ".");
} else {
modifiedLink = link;
}
} else if (!link.startsWith("http://") && !link.startsWith("https://")) {
modifiedLink = "https://" + link;
} else {
modifiedLink = link;
}
return modifiedLink;
}
private static Cell[] createDataCellsInRow(Row row, int startColumn, CellStyle cellStyle, String... names) {
Cell[] result = new Cell[names.length];
for (int i = 0; i < names.length; i++) {
Cell cell = row.createCell(startColumn + i, CellType.STRING);
if (cellStyle != null) {
cell.setCellStyle(cellStyle);
}
if (!StringUtils.isEmpty(names[i])) {
final String value;
final int maxCellStringLength = Short.MAX_VALUE;
if (names[i].length() > maxCellStringLength) {
value = names[i].substring(0, maxCellStringLength - 3) + "...";
} else {
value = names[i];
}
cell.setCellValue(value);
}
result[i] = cell;
}
return result;
}
/**
* Create cells for InfoFile content.
*
* @param row The row to insert cells into.
* @param cellStyle The cell style of the created cell.
* @param startPositions The start position of the 3 columns for an InfoFile.
*/
private static void createInfoFileCellsInRow(Row row, CellStyle cellStyle, int... startPositions) {
for (int startPosition : startPositions) {
createCellsInRow(row, startPosition, cellStyle, "Content", "Extracted copyright lines", "File");
}
}
private static void createCellsInRow(Row row, int startColumn, CellStyle cellStyle, String... names) {
for (int i = 0; i < names.length; i++) {
Cell cell = row.createCell(startColumn + i, CellType.STRING);
cell.setCellStyle(cellStyle);
cell.setCellValue(names[i]);
}
}
private static void createMergedCellsInRow(
Sheet sheet, int startColumn, int endColumn, CellStyle cellStyle, Row row, String cellValue, int rowIndex) {
Cell cell = createCellsInRow(startColumn, endColumn, row);
if (cell == null) {
return;
}
final boolean merge = endColumn - 1 > startColumn;
CellRangeAddress mergeAddress = null;
if (merge) {
mergeAddress = new CellRangeAddress(rowIndex, rowIndex, startColumn, endColumn - 1);
sheet.addMergedRegion(mergeAddress);
}
// Set value and style only after merge
cell.setCellValue(cellValue);
cell.setCellStyle(cellStyle);
if (merge) {
setBorderAroundRegion(sheet, mergeAddress, HEADER_CELLS_BORDER_STYLE);
sheet.groupColumn(startColumn, endColumn - 1);
}
}
private static void setBorderAroundRegion(
Sheet sheet, CellRangeAddress licensesHeaderAddress, BorderStyle borderStyle) {
RegionUtil.setBorderLeft(borderStyle, licensesHeaderAddress, sheet);
RegionUtil.setBorderTop(borderStyle, licensesHeaderAddress, sheet);
RegionUtil.setBorderRight(borderStyle, licensesHeaderAddress, sheet);
RegionUtil.setBorderBottom(borderStyle, licensesHeaderAddress, sheet);
}
private static Cell createCellsInRow(int startColumn, int exclusiveEndColumn, Row inRow) {
Cell firstCell = null;
for (int i = startColumn; i < exclusiveEndColumn; i++) {
Cell cell = inRow.createCell(i);
if (i == startColumn) {
firstCell = cell;
}
}
return firstCell;
}
private static void setBorderStyle(CellStyle cellStyle, BorderStyle borderStyle) {
cellStyle.setBorderLeft(borderStyle);
cellStyle.setBorderTop(borderStyle);
cellStyle.setBorderRight(borderStyle);
cellStyle.setBorderBottom(borderStyle);
}
/**
* Parameters for cells which apply to all cells in each loop iteration.
*/
private static class CellListParameter {
private final Sheet sheet;
private final Map rows;
private final CellStyle cellStyle;
private CellListParameter(Sheet sheet, Map rows, CellStyle cellStyle) {
this.sheet = sheet;
this.rows = rows;
this.cellStyle = cellStyle;
}
Sheet getSheet() {
return sheet;
}
Map getRows() {
return rows;
}
CellStyle getCellStyle() {
return cellStyle;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy