Skip to content

Check null to avoid null pointer exception #334

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

Merged
merged 10 commits into from
May 31, 2025
73 changes: 52 additions & 21 deletions src/main/java/org/spdx/utility/compare/LicenseCompareHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Collection;
import javax.annotation.Nullable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -122,12 +123,15 @@ public static String removeCommentChars(String s) {
}

/**
* Locate the original text starting with the start token and ending with the end token
* Locate the original text starting with the start token and ending with the
* end token
*
* @param fullLicenseText entire license text
* @param startToken starting token
* @param endToken ending token
* @param startToken starting token
* @param endToken ending token
* @param tokenToLocation token location
* @return original text starting with the start token and ending with the end token
* @return original text starting with the start token and ending with the end
* token
*/
public static String locateOriginalText(String fullLicenseText, int startToken, int endToken,
Map<Integer, LineColumn> tokenToLocation, String[] tokens) {
Expand Down Expand Up @@ -190,12 +194,25 @@ public static String locateOriginalText(String fullLicenseText, int startToken,
}
// ignore
}

/*
* @param text text to test
* @return the first token in the license text

/**
* Return the first license token found in the given text
* <p>
* The method normalizes the input text, removes comment characters,
* and splits it into tokens
* using {@link LicenseTextHelper#TOKEN_SPLIT_PATTERN}.
* It returns the first non-empty token found,
* or {@code null} if no such token exists.
* </p>
*
* @param text The license text to extract the first token from.
* @return The first non-empty token as a {@link String},
* or {@code null} if none is found.
*/
public static String getFirstLicenseToken(String text) {
public static @Nullable String getFirstLicenseToken(@Nullable String text) {
if (text == null || text.isEmpty()) {
return null;
}
String textToTokenize = LicenseTextHelper.normalizeText(LicenseTextHelper.replaceMultWord(LicenseTextHelper.replaceSpaceComma(
LicenseTextHelper.removeLineSeparators(removeCommentChars(text))))).toLowerCase();
Matcher m = LicenseTextHelper.TOKEN_SPLIT_PATTERN.matcher(textToTokenize);
Expand All @@ -206,32 +223,42 @@ public static String getFirstLicenseToken(String text) {
}
return null;
}

/**
* @param text text to test
* @return true if the text contains a single token
* Check whether the given text contains only a single token
* <p>
* A single token string is a string that contains zero or one token,
* as identified by the {@link LicenseTextHelper#TOKEN_SPLIT_PATTERN}.
* Whitespace and punctuation such as dots, commas, question marks,
* and quotation marks are ignored.
* </p>
*
* @param text The text to test.
* @return {@code true} if the text contains zero or one token,
* {@code false} otherwise.
*/
public static boolean isSingleTokenString(String text) {
if (text.contains("\n")) {
return false;
public static boolean isSingleTokenString(@Nullable String text) {
if (text == null || text.isEmpty()) {
return true; // Zero tokens is considered a single token string
}
Matcher m = LicenseTextHelper.TOKEN_SPLIT_PATTERN.matcher(text);
boolean found = false;
while (m.find()) {
if (!m.group(1).trim().isEmpty()) {
if (found) {
return false;
return false; // More than one eligible token found
} else {
found = true;
found = true; // First eligible token found
}
}
}
return true;
return true; // Zero or one eligible token found
}

/**
* Compares two licenses from potentially two different documents which may have
* different license ID's for the same license
*
* @param license1 first license to compare
* @param license2 second license to compare
* @param xlationMap Mapping the license ID's from license 1 to license 2
Expand Down Expand Up @@ -342,11 +369,15 @@ public static List<String> getNonOptionalLicenseText(String licenseTemplate,
}

/**
* @param template Template in the standard template format used for comparison
* Compare the provided text against a license template using SPDX matching
* guidelines
*
* @param template Template in the standard template format used for
* comparison
* @param compareText Text to compare using the template
* @return any differences found
* @return Any differences found
* @throws SpdxCompareException on comparison errors
*/
*/
public static DifferenceDescription isTextMatchingTemplate(String template, String compareText) throws SpdxCompareException {
CompareTemplateOutputHandler compareTemplateOutputHandler;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,18 +539,33 @@ public void testLicenseEqualsNoneLicense() throws InvalidSPDXAnalysisException,
Map<String, String> xlationMap = new HashMap<>();;
assertTrue(LicenseCompareHelper.isLicenseEqual(lic3, lic4, xlationMap));
assertFalse(LicenseCompareHelper.isLicenseEqual(lic4, lic2, xlationMap));
}


}

public void testisSingleTokenString() {
assertTrue(LicenseCompareHelper.isSingleTokenString(" token "));
assertTrue(LicenseCompareHelper.isSingleTokenString(null));
assertTrue(LicenseCompareHelper.isSingleTokenString(""));
assertTrue(LicenseCompareHelper.isSingleTokenString(" "));
assertTrue(LicenseCompareHelper.isSingleTokenString("\n"));
assertTrue(LicenseCompareHelper.isSingleTokenString("'"));
assertTrue(LicenseCompareHelper.isSingleTokenString(" '"));
assertTrue(LicenseCompareHelper.isSingleTokenString("' "));
assertTrue(LicenseCompareHelper.isSingleTokenString("''"));
assertTrue(LicenseCompareHelper.isSingleTokenString("token"));
assertTrue(LicenseCompareHelper.isSingleTokenString(" token"));
assertTrue(LicenseCompareHelper.isSingleTokenString(" token "));
assertTrue(LicenseCompareHelper.isSingleTokenString("token\n"));
assertTrue(LicenseCompareHelper.isSingleTokenString("\ntoken"));
assertTrue(LicenseCompareHelper.isSingleTokenString(" \n token "));
assertTrue(LicenseCompareHelper.isSingleTokenString(":;token?"));
assertTrue(LicenseCompareHelper.isSingleTokenString("'''token"));
assertTrue(LicenseCompareHelper.isSingleTokenString("token'''"));
assertFalse(LicenseCompareHelper.isSingleTokenString("a and"));
assertFalse(LicenseCompareHelper.isSingleTokenString("a\nand"));
assertFalse(LicenseCompareHelper.isSingleTokenString("a and "));
assertFalse(LicenseCompareHelper.isSingleTokenString(" a and"));
assertFalse(LicenseCompareHelper.isSingleTokenString(" a.and"));
}

public void regressionTestMatchingGpl20Only() throws IOException, InvalidSPDXAnalysisException, SpdxCompareException {
String compareText = UnitTestHelper.fileToText(GPL_2_TEXT);
DifferenceDescription result = LicenseCompareHelper.isTextStandardLicense(LicenseInfoFactory.getListedLicenseById("GPL-2.0-only"), compareText);
Expand All @@ -568,11 +583,16 @@ public void testMatchingStandardLicenseIds() throws IOException, InvalidSPDXAnal
assertTrue(result[3].startsWith("GPL-2"));
}
}

public void testFirstLicenseToken() {
assertEquals("first", LicenseCompareHelper.getFirstLicenseToken(" first,token that is needed\nnext"));
assertEquals("first", LicenseCompareHelper.getFirstLicenseToken("// first,second"));
assertNull(LicenseCompareHelper.getFirstLicenseToken(null));
assertNull(LicenseCompareHelper.getFirstLicenseToken(""));
assertNull(LicenseCompareHelper.getFirstLicenseToken(" <!-- -->"));
assertNull(LicenseCompareHelper.getFirstLicenseToken("# "));
}

@SuppressWarnings("unused")
private String stringCharToUnicode(String s, int location) {
return "\\u" + Integer.toHexString(s.charAt(location) | 0x10000).substring(1);
Expand Down