org.spdx.spdxspreadsheet.SnippetSheet Maven / Gradle / Ivy
/**
* Copyright (c) 2016 Source Auditor Inc.
*
* 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 org.spdx.spdxspreadsheet;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spdx.rdfparser.InvalidSPDXAnalysisException;
import org.spdx.rdfparser.SpdxDocumentContainer;
import org.spdx.rdfparser.license.AnyLicenseInfo;
import org.spdx.rdfparser.license.LicenseInfoFactory;
import org.spdx.rdfparser.model.Annotation;
import org.spdx.rdfparser.model.Relationship;
import org.spdx.rdfparser.model.SpdxElement;
import org.spdx.rdfparser.model.SpdxFile;
import org.spdx.rdfparser.model.SpdxSnippet;
import org.spdx.rdfparser.model.pointer.ByteOffsetPointer;
import org.spdx.rdfparser.model.pointer.LineCharPointer;
import org.spdx.rdfparser.model.pointer.SinglePointer;
import org.spdx.rdfparser.model.pointer.StartEndPointer;
import com.google.common.collect.Maps;
/**
* Sheet to hold all snippet information
* @author Gary O'Neall
*
*/
public class SnippetSheet extends AbstractSheet {
static final Logger logger = LoggerFactory.getLogger(SnippetSheet.class);
static final int ID_COL = 0;
static final int NAME_COL = ID_COL + 1;
static final int SNIPPET_FROM_FILE_ID_COL = NAME_COL + 1;
static final int BYTE_RANGE_COL = SNIPPET_FROM_FILE_ID_COL + 1;
static final int LINE_RANGE_COL = BYTE_RANGE_COL + 1;
static final int CONCLUDED_LICENSE_COL = LINE_RANGE_COL + 1;
static final int LICENSE_INFO_IN_SNIPPET_COL = CONCLUDED_LICENSE_COL + 1;
static final int LICENSE_COMMENT_COL = LICENSE_INFO_IN_SNIPPET_COL + 1;
static final int COPYRIGHT_COL = LICENSE_COMMENT_COL + 1;
static final int COMMENT_COL = COPYRIGHT_COL + 1;
static final int USER_DEFINED_COLS = COMMENT_COL + 1;
static final int NUM_COLS = USER_DEFINED_COLS + 1;
static final boolean[] REQUIRED = new boolean[] {true, false, true, true, false,
false, false, false, false, false, false};
static final String[] HEADER_TITLES = new String[] {"ID", "Name", "From File ID",
"Byte Range", "Line Range", "License Concluded", "License Info in Snippet", "License Comments",
"Snippet Copyright Text", "Comment", "User Defined Columns..."};
static final int[] COLUMN_WIDTHS = new int[] {25, 25, 25, 40, 40, 60, 60, 60, 60, 60, 40};
static final boolean[] LEFT_WRAP = new boolean[] {false, false, false, false, false,
true, true, true, true, true, true};
static final boolean[] CENTER_NOWRAP = new boolean[] {true, true, true, true, true,
false, false, false, false, false, false};
private static Pattern NUMBER_RANGE_PATTERN = Pattern.compile("(\\d+):(\\d+)");
/**
* Hashmap of the snippet ID to SPDX snipet
*/
Map snippetCache = Maps.newHashMap();
/**
* @param workbook
* @param snippetSheetName
*/
public SnippetSheet(Workbook workbook, String snippetSheetName) {
super(workbook, snippetSheetName);
}
/* (non-Javadoc)
* @see org.spdx.spdxspreadsheet.AbstractSheet#verify()
*/
@Override
public String verify() {
try {
if (sheet == null) {
return "Worksheet for SPDX Snippets does not exist";
}
Row firstRow = sheet.getRow(firstRowNum);
for (int i = 0; i < NUM_COLS- 1; i++) { // Don't check the last (user defined) column
Cell cell = firstRow.getCell(i+firstCellNum);
if (cell == null ||
cell.getStringCellValue() == null ||
!cell.getStringCellValue().equals(HEADER_TITLES[i])) {
return "Column "+HEADER_TITLES[i]+" missing for SPDX Snippet worksheet";
}
}
// validate rows
boolean done = false;
int rowNum = getFirstDataRow();
while (!done) {
Row row = sheet.getRow(rowNum);
if (row == null || row.getCell(firstCellNum) == null) {
done = true;
} else {
String error = validateRow(row);
if (error != null) {
return error;
}
rowNum++;
}
}
return null;
} catch (Exception ex) {
return "Error in verifying SPDX Snippet work sheet: "+ex.getMessage();
}
}
/**
* @param row
* @return
*/
private String validateRow(Row row) {
for (int i = 0; i < NUM_COLS; i++) {
Cell cell = row.getCell(i);
if (cell == null) {
if (REQUIRED[i]) {
return "Required cell "+HEADER_TITLES[i]+" missing for row "+String.valueOf(row.getRowNum());
}
} else {
if (i == CONCLUDED_LICENSE_COL) {
try {
LicenseInfoFactory.parseSPDXLicenseString(cell.getStringCellValue(), null);
} catch (SpreadsheetException ex) {
return "Invalid asserted license string in row "+String.valueOf(row.getRowNum()) +
" details: "+ex.getMessage();
}
} else if (i == BYTE_RANGE_COL || i == LINE_RANGE_COL) {
String range = cell.getStringCellValue();
if (range != null && !range.isEmpty()) {
Matcher rangeMatcher = NUMBER_RANGE_PATTERN.matcher(cell.getStringCellValue());
if (!rangeMatcher.matches()) {
return "Invalid range for "+HEADER_TITLES[i]+": "+cell.getStringCellValue();
}
int start = 0;
int end = 0;
try {
start = Integer.parseInt(rangeMatcher.group(1));
end = Integer.parseInt(rangeMatcher.group(2));
if (start >= end) {
return "Invalid range for "+HEADER_TITLES[i]+": "+cell.getStringCellValue() + ". End is not greater than or equal to the end.";
}
} catch(Exception ex) {
return "Invalid range for "+HEADER_TITLES[i]+": "+cell.getStringCellValue();
}
}
}
}
}
return null;
}
public static void create(Workbook wb, String sheetName) {
int sheetNum = wb.getSheetIndex(sheetName);
if (sheetNum >= 0) {
wb.removeSheetAt(sheetNum);
}
Sheet sheet = wb.createSheet(sheetName);
CellStyle headerStyle = AbstractSheet.createHeaderStyle(wb);
CellStyle centerStyle = AbstractSheet.createCenterStyle(wb);
CellStyle wrapStyle = AbstractSheet.createLeftWrapStyle(wb);
Row row = sheet.createRow(0);
for (int i = 0; i < HEADER_TITLES.length; i++) {
sheet.setColumnWidth(i, COLUMN_WIDTHS[i]*256);
if (LEFT_WRAP[i]) {
sheet.setDefaultColumnStyle(i, wrapStyle);
} else if (CENTER_NOWRAP[i]) {
sheet.setDefaultColumnStyle(i, centerStyle);
}
Cell cell = row.createCell(i);
cell.setCellStyle(headerStyle);
cell.setCellValue(HEADER_TITLES[i]);
}
}
/**
* @param snippet
* @throws SpreadsheetException
*/
public void add(SpdxSnippet snippet) throws SpreadsheetException {
Row row = addRow();
if (snippet.getId() != null && !snippet.getId().isEmpty()) {
row.createCell(ID_COL).setCellValue(snippet.getId());
}
if (snippet.getName() != null && !snippet.getName().isEmpty()) {
row.createCell(NAME_COL).setCellValue(snippet.getName());
}
SpdxFile snippetFromFile;
try {
snippetFromFile = snippet.getSnippetFromFile();
} catch (InvalidSPDXAnalysisException e) {
logger.error("Error getting the snippetFromFile",e);
throw new SpreadsheetException("Unable to get the Snippet from File from the Snippet: "+e.getMessage());
}
if (snippetFromFile != null && snippetFromFile.getId() != null) {
row.createCell(SNIPPET_FROM_FILE_ID_COL).setCellValue(snippetFromFile.getId());
}
StartEndPointer byteRange;
try {
byteRange = snippet.getByteRange();
} catch (InvalidSPDXAnalysisException e) {
logger.error("Error getting the byteRange",e);
throw new SpreadsheetException("Unable to get the byte range from the Snippet: "+e.getMessage());
}
if (byteRange != null) {
try {
row.createCell(BYTE_RANGE_COL).setCellValue(rangeToStr(byteRange));
} catch (InvalidSPDXAnalysisException e) {
logger.error("Invalid byte range",e);
throw new SpreadsheetException("Invalid byte range: "+e.getMessage());
}
}
StartEndPointer lineRange;
try {
lineRange = snippet.getLineRange();
} catch (InvalidSPDXAnalysisException e) {
logger.error("Error getting the lineRange",e);
throw new SpreadsheetException("Unable to get the line range from the Snippet: "+e.getMessage());
}
if (lineRange != null) {
try {
row.createCell(LINE_RANGE_COL).setCellValue(rangeToStr(lineRange));
} catch (InvalidSPDXAnalysisException e) {
logger.error("Invalid line range",e);
throw new SpreadsheetException("Invalid line range: "+e.getMessage());
}
}
if (snippet.getLicenseConcluded() != null) {
row.createCell(CONCLUDED_LICENSE_COL).setCellValue(snippet.getLicenseConcluded().toString());
}
AnyLicenseInfo[] licenseInfoFromSnippet = snippet.getLicenseInfoFromFiles();
if (licenseInfoFromSnippet != null && licenseInfoFromSnippet.length > 0) {
row.createCell(LICENSE_INFO_IN_SNIPPET_COL).setCellValue(PackageInfoSheet.licensesToString(licenseInfoFromSnippet));
}
if (snippet.getLicenseComments() != null) {
row.createCell(LICENSE_COMMENT_COL).setCellValue(snippet.getLicenseComments());
}
if (snippet.getCopyrightText() != null) {
row.createCell(COPYRIGHT_COL).setCellValue(snippet.getCopyrightText());
}
if (snippet.getComment() != null) {
row.createCell(COMMENT_COL).setCellValue(snippet.getComment());
}
this.snippetCache.put(snippet.getId(), snippet);
}
/**
* @param byteRange
* @return
* @throws InvalidSPDXAnalysisException
*/
private String rangeToStr(StartEndPointer rangePointer) throws InvalidSPDXAnalysisException {
SinglePointer startPointer = rangePointer.getStartPointer();
if (startPointer == null) {
throw new InvalidSPDXAnalysisException("Missing start pointer");
}
SinglePointer endPointer = rangePointer.getEndPointer();
if (endPointer == null) {
throw new InvalidSPDXAnalysisException("Missing end pointer");
}
String start = null;
if (startPointer instanceof ByteOffsetPointer) {
start = String.valueOf(((ByteOffsetPointer)startPointer).getOffset());
} else if (startPointer instanceof LineCharPointer) {
start = String.valueOf(((LineCharPointer)startPointer).getLineNumber());
} else {
logger.error("Unknown pointer type for start pointer "+startPointer.toString());
throw new InvalidSPDXAnalysisException("Unknown pointer type for start pointer");
}
String end = null;
if (endPointer instanceof ByteOffsetPointer) {
end = String.valueOf(((ByteOffsetPointer)endPointer).getOffset());
} else if (endPointer instanceof LineCharPointer) {
end = String.valueOf(((LineCharPointer)endPointer).getLineNumber());
} else {
logger.error("Unknown pointer type for start pointer "+startPointer.toString());
throw new InvalidSPDXAnalysisException("Unknown pointer type for start pointer");
}
return start + ":" + end;
}
/**
* Get the SPDX snippet represented in the row rownum.
* IMPORTANT: The Snippet From File will only be filled in if the associated file is found in the container.
* This property can be set after calling getSnippet if the model is not already populated with the file
* The ID from the Snippet From File can be obtained through the getSnippetFileId(int rowNum)
method
* @param rowNum
* @return Snippet at the row rowNum or null if the row does not exist
* @throws SpreadsheetException
*/
public SpdxSnippet getSnippet(int rowNum, SpdxDocumentContainer container) throws SpreadsheetException {
if (sheet == null) {
return null;
}
Row row = sheet.getRow(rowNum);
if (row == null) {
return null;
}
String ver = validateRow(row);
if (ver != null && !ver.isEmpty()) {
throw(new SpreadsheetException(ver));
}
String id = null;
if (row.getCell(ID_COL) != null) {
id = row.getCell(ID_COL).getStringCellValue();
}
if (this.snippetCache.containsKey(id)) {
return this.snippetCache.get(id);
}
String name = null;
if (row.getCell(NAME_COL) != null) {
name = row.getCell(NAME_COL).getStringCellValue();
}
StartEndPointer byteRange = null;
if (row.getCell(BYTE_RANGE_COL) != null) {
String range = row.getCell(BYTE_RANGE_COL).getStringCellValue();
if (range != null && !range.isEmpty()) {
int start = 0;
int end = 0;
Matcher rangeMatcher = NUMBER_RANGE_PATTERN.matcher(range);
if (!rangeMatcher.matches()) {
throw new SpreadsheetException("Invalid byte range: "+range);
}
try {
start = Integer.parseInt(rangeMatcher.group(1));
end = Integer.parseInt(rangeMatcher.group(2));
} catch(Exception ex) {
throw new SpreadsheetException("Invalid byte range: "+range);
}
// Note: the reference should be filled in when the snippetFromFile is set for the Spdx Snippet
ByteOffsetPointer startPointer = new ByteOffsetPointer(null, start);
ByteOffsetPointer endPointer = new ByteOffsetPointer(null, end);
byteRange = new StartEndPointer(startPointer, endPointer);
}
}
StartEndPointer lineRange = null;
if (row.getCell(LINE_RANGE_COL) != null) {
String range = row.getCell(LINE_RANGE_COL).getStringCellValue();
if (range != null && !range.isEmpty()) {
int start = 0;
int end = 0;
Matcher rangeMatcher = NUMBER_RANGE_PATTERN.matcher(range);
if (!rangeMatcher.matches()) {
throw new SpreadsheetException("Invalid line range: "+range);
}
try {
start = Integer.valueOf(rangeMatcher.group(1));
end = Integer.valueOf(rangeMatcher.group(2));
} catch(Exception ex) {
throw new SpreadsheetException("Invalid line range: "+range);
}
// Note: the reference should be filled in when the snippetFromFile is set for the Spdx Snippet
LineCharPointer startPointer = new LineCharPointer(null, start);
LineCharPointer endPointer = new LineCharPointer(null, end);
lineRange = new StartEndPointer(startPointer, endPointer);
}
}
AnyLicenseInfo concludedLicense = null;
Cell concludedLicenseCell = row.getCell(CONCLUDED_LICENSE_COL);
if (concludedLicenseCell != null && !concludedLicenseCell.getStringCellValue().isEmpty()) {
concludedLicense = LicenseInfoFactory.parseSPDXLicenseString(concludedLicenseCell.getStringCellValue(), container);
} else {
concludedLicense = null;
}
AnyLicenseInfo[] seenLicenses = new AnyLicenseInfo[0];
Cell seenLicenseCell = row.getCell(LICENSE_INFO_IN_SNIPPET_COL);
if (seenLicenseCell != null && !seenLicenseCell.getStringCellValue().isEmpty()) {
String[] licenseStrings = seenLicenseCell.getStringCellValue().split(",");
seenLicenses = new AnyLicenseInfo[licenseStrings.length];
for (int i = 0; i < licenseStrings.length; i++) {
seenLicenses[i] = LicenseInfoFactory.parseSPDXLicenseString(licenseStrings[i].trim(), container);
}
} else {
seenLicenses = null;
}
String licenseComments = null;
Cell licCommentCell = row.getCell(LICENSE_COMMENT_COL);
if (licCommentCell != null) {
licenseComments = licCommentCell.getStringCellValue();
} else {
licenseComments = "";
}
String copyright;
Cell copyrightCell = row.getCell(COPYRIGHT_COL);
if (copyrightCell != null) {
copyright = copyrightCell.getStringCellValue();
} else {
copyright = "";
}
String comment = null;
Cell commentCell = row.getCell(COMMENT_COL);
if (commentCell != null) {
comment = commentCell.getStringCellValue();
}
String snippetFromFileId = getSnippetFileId(rowNum);
SpdxFile snippetFromFile = null;
if (snippetFromFileId != null && !snippetFromFileId.isEmpty()) {
SpdxElement fromFileElement;
try {
fromFileElement = container.findElementById(snippetFromFileId);
if (fromFileElement instanceof SpdxFile) {
snippetFromFile = (SpdxFile)fromFileElement;
// Fix up the ranges to reference this snippetFromFile
if (byteRange != null) {
byteRange.getStartPointer().setReference(snippetFromFile);
byteRange.getEndPointer().setReference(snippetFromFile);
}
if (lineRange != null) {
lineRange.getStartPointer().setReference(snippetFromFile);
lineRange.getEndPointer().setReference(snippetFromFile);
}
} else {
logger.warn("Element associated with the snippetFromFile is not of type SPDX File. Null will be used");
}
} catch (InvalidSPDXAnalysisException e) {
logger.warn("Error getting snipet from file by ID. snippetFromFile will be set to null");
}
}
SpdxSnippet retval = new SpdxSnippet(name, comment, new Annotation[0], new Relationship[0],
concludedLicense, seenLicenses, copyright, licenseComments, snippetFromFile,
byteRange, lineRange);
try {
retval.setId(id);
} catch (InvalidSPDXAnalysisException e) {
logger.error("Error setting ID for SpdxSnippet", e);
throw new SpreadsheetException("Error setting ID for SpdxSnippet: "+e.getMessage());
}
this.snippetCache.put(id, retval);
return retval;
}
/**
* Get the SpdxFromFileSNippet for the given row
* @param rowNum
* @return
* @throws SpreadsheetException
*/
public String getSnippetFileId(int rowNum) throws SpreadsheetException {
Row row = sheet.getRow(rowNum);
if (row == null) {
return null;
}
String ver = validateRow(row);
if (ver != null && !ver.isEmpty()) {
throw(new SpreadsheetException(ver));
}
String id = null;
if (row.getCell(SNIPPET_FROM_FILE_ID_COL) != null) {
id = row.getCell(SNIPPET_FROM_FILE_ID_COL).getStringCellValue();
}
return id;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy