Skip to content

Commit

Permalink
Add functions to return maps of licenses (#290)
Browse files Browse the repository at this point in the history
* Add functions to retun maps of licenses

Fixes #237

* Use map for fetching listed licenses

* Make SPDX spec 2 license map getters protected

---------

Signed-off-by: Gary O'Neall <[email protected]>
  • Loading branch information
goneall authored Jan 31, 2025
1 parent 9d224cd commit 77f3f78
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 53 deletions.
164 changes: 133 additions & 31 deletions src/main/java/org/spdx/library/ListedLicenses.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

Expand All @@ -33,6 +30,7 @@
import org.spdx.library.model.v2.SpdxConstantsCompatV2;
import org.spdx.library.model.v2.SpdxModelFactoryCompatV2;
import org.spdx.library.model.v2.license.SpdxListedLicense;
import org.spdx.library.model.v2.license.SpdxListedLicenseException;
import org.spdx.library.model.v3_0_1.core.CreationInfo;
import org.spdx.library.model.v3_0_1.expandedlicensing.ListedLicense;
import org.spdx.library.model.v3_0_1.expandedlicensing.ListedLicenseException;
Expand Down Expand Up @@ -62,6 +60,11 @@ public class ListedLicenses {
private SpdxV2ListedLicenseModelStore licenseStoreV2;
private SpdxV3ListedLicenseModelStore licenseStoreV3;
private static ListedLicenses listedLicenses = null;
private Map<String, SpdxListedLicense> spdxListedLicenseMapCompatV2;
private Map<String, ListedLicense> spdxListedLicenseMap;
private Map<String, org.spdx.library.model.v2.license.ListedLicenseException> spdxListedExceptionMapCompatV2;
private Map<String, ListedLicenseException> spdxListedExceptionMap;

/**
* Lock for any modifications to the underlying licenseModelStore
*/
Expand Down Expand Up @@ -201,13 +204,7 @@ public boolean isSpdxListedExceptionId(String exceptionId) {
* @throws InvalidSPDXAnalysisException on SPDX parsing error
*/
public SpdxListedLicense getListedLicenseByIdCompatV2(String licenseId) throws InvalidSPDXAnalysisException {
try {
return (SpdxListedLicense)SpdxModelFactoryCompatV2.getModelObjectV2(this.licenseStoreV2,
SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX, licenseId,
SpdxConstantsCompatV2.CLASS_SPDX_LISTED_LICENSE, null, false);
} catch (SpdxIdNotFoundException ex) {
return null;
}
return getSpdxListedLicensesCompatV2().get(licenseId);
}

/**
Expand All @@ -216,13 +213,7 @@ public SpdxListedLicense getListedLicenseByIdCompatV2(String licenseId) throws I
* @throws InvalidSPDXAnalysisException on SPDX parsing error
*/
public org.spdx.library.model.v2.license.ListedLicenseException getListedExceptionByIdCompatV2(String exceptionId) throws InvalidSPDXAnalysisException {
try {
return (org.spdx.library.model.v2.license.ListedLicenseException)SpdxModelFactoryCompatV2.getModelObjectV2(
this.licenseStoreV2, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX,
exceptionId, SpdxConstantsCompatV2.CLASS_SPDX_LISTED_LICENSE_EXCEPTION, null, false);
} catch (SpdxIdNotFoundException ex) {
return null;
}
return getSpdxListedLicenseExceptionsCompatV2().get(exceptionId);
}

/**
Expand All @@ -231,22 +222,11 @@ public org.spdx.library.model.v2.license.ListedLicenseException getListedExcepti
* @throws InvalidSPDXAnalysisException on SPDX parsing error
*/
public ListedLicense getListedLicenseById(String licenseId) throws InvalidSPDXAnalysisException {
try {
return new ListedLicense(this.licenseStoreV3, SpdxListedLicenseModelStore.licenseOrExceptionIdToObjectUri(licenseId), null,
false, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX);
} catch (SpdxIdNotFoundException ex) {
return null;
}

return getSpdxListedLicenses().get(licenseId);
}

public ListedLicenseException getListedExceptionById(String exceptionId) throws InvalidSPDXAnalysisException {
try {
return new ListedLicenseException(this.licenseStoreV3, SpdxListedLicenseModelStore.licenseOrExceptionIdToObjectUri(exceptionId), null,
false, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX);
} catch (SpdxIdNotFoundException ex) {
return null;
}
return getSpdxListedLicenseExceptions().get(exceptionId);

}

Expand All @@ -261,6 +241,128 @@ public List<String> getSpdxListedLicenseIds() {
listedLicenseModificationLock.readLock().unlock();
}
}

/**
* @return a map of SPDX listed license IDs to the SPDX listed license
* @throws InvalidSPDXAnalysisException on errors fetching the licenses
*/
public Map<String, ListedLicense> getSpdxListedLicenses() throws InvalidSPDXAnalysisException {
listedLicenseModificationLock.readLock().lock();
try {
if (Objects.nonNull(this.spdxListedLicenseMap)) {
return this.spdxListedLicenseMap;
}
} finally {
listedLicenseModificationLock.readLock().unlock();
}
listedLicenseModificationLock.writeLock().lock();
try {
if (Objects.nonNull(this.spdxListedLicenseMap)) {
return this.spdxListedLicenseMap;
}
Map<String, ListedLicense> allListedLicenses = new HashMap<>();
for (String licenseId : this.baseModelStore.getSpdxListedLicenseIds()) {
allListedLicenses.put(licenseId, new ListedLicense(this.licenseStoreV3, SpdxListedLicenseModelStore.licenseOrExceptionIdToObjectUri(licenseId), null,
false, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX));
}
this.spdxListedLicenseMap = Collections.unmodifiableMap(allListedLicenses);
return this.spdxListedLicenseMap;
} finally {
listedLicenseModificationLock.writeLock().unlock();
}
}

/**
* @return a map of SPDX listed license exception IDs to the SPDX listed license exception
* @throws InvalidSPDXAnalysisException on errors fetching the license exceptions
*/
public Map<String, ListedLicenseException> getSpdxListedLicenseExceptions() throws InvalidSPDXAnalysisException {
listedLicenseModificationLock.readLock().lock();
try {
if (Objects.nonNull(this.spdxListedExceptionMap)) {
return this.spdxListedExceptionMap;
}
} finally {
listedLicenseModificationLock.readLock().unlock();
}
listedLicenseModificationLock.writeLock().lock();
try {
if (Objects.nonNull(this.spdxListedExceptionMap)) {
return this.spdxListedExceptionMap;
}
Map<String, ListedLicenseException> allListedExceptions = new HashMap<>();
for (String exceptionId : this.baseModelStore.getSpdxListedExceptionIds()) {
allListedExceptions.put(exceptionId, new ListedLicenseException(this.licenseStoreV3, SpdxListedLicenseModelStore.licenseOrExceptionIdToObjectUri(exceptionId), null,
false, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX));
}
this.spdxListedExceptionMap = Collections.unmodifiableMap(allListedExceptions);
return this.spdxListedExceptionMap;
} finally {
listedLicenseModificationLock.writeLock().unlock();
}
}

/**
* @return a map of SPDX listed license IDs to the SPDX Spec version 2 listed license
* @throws InvalidSPDXAnalysisException on errors fetching the licenses
*/
protected Map<String, SpdxListedLicense> getSpdxListedLicensesCompatV2() throws InvalidSPDXAnalysisException {
listedLicenseModificationLock.readLock().lock();
try {
if (Objects.nonNull(this.spdxListedLicenseMapCompatV2)) {
return this.spdxListedLicenseMapCompatV2;
}
} finally {
listedLicenseModificationLock.readLock().unlock();
}
listedLicenseModificationLock.writeLock().lock();
try {
if (Objects.nonNull(this.spdxListedLicenseMapCompatV2)) {
return this.spdxListedLicenseMapCompatV2;
}
Map<String, SpdxListedLicense> allListedLicenses = new HashMap<>();
for (String licenseId : this.baseModelStore.getSpdxListedLicenseIds()) {
allListedLicenses.put(licenseId, (SpdxListedLicense)SpdxModelFactoryCompatV2.getModelObjectV2(this.licenseStoreV2,
SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX, licenseId,
SpdxConstantsCompatV2.CLASS_SPDX_LISTED_LICENSE, null, false));
}
this.spdxListedLicenseMapCompatV2 = Collections.unmodifiableMap(allListedLicenses);
return this.spdxListedLicenseMapCompatV2;
} finally {
listedLicenseModificationLock.writeLock().unlock();
}
}

/**
* @return a map of SPDX listed license exception IDs to the SPDX listed license exception
* @throws InvalidSPDXAnalysisException on errors fetching the license exceptions
*/
protected Map<String, org.spdx.library.model.v2.license.ListedLicenseException> getSpdxListedLicenseExceptionsCompatV2() throws InvalidSPDXAnalysisException {
listedLicenseModificationLock.readLock().lock();
try {
if (Objects.nonNull(this.spdxListedExceptionMapCompatV2)) {
return this.spdxListedExceptionMapCompatV2;
}
} finally {
listedLicenseModificationLock.readLock().unlock();
}
listedLicenseModificationLock.writeLock().lock();
try {
if (Objects.nonNull(this.spdxListedExceptionMapCompatV2)) {
return this.spdxListedExceptionMapCompatV2;
}
Map<String, org.spdx.library.model.v2.license.ListedLicenseException> allListedExceptions = new HashMap<>();
for (String exceptionId : this.baseModelStore.getSpdxListedExceptionIds()) {
allListedExceptions.put(exceptionId, (org.spdx.library.model.v2.license.ListedLicenseException)SpdxModelFactoryCompatV2.getModelObjectV2(
this.licenseStoreV2, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX,
exceptionId, SpdxConstantsCompatV2.CLASS_SPDX_LISTED_LICENSE_EXCEPTION, null, false));
}
this.spdxListedExceptionMapCompatV2 = Collections.unmodifiableMap(allListedExceptions);
return this.spdxListedExceptionMapCompatV2;
} finally {
listedLicenseModificationLock.writeLock().unlock();
}
}

/**
* @return The version of the loaded license list in the form M.N, where M is the major release and N is the minor release.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ public boolean isPropertyValueAssignableTo(PropertyDescriptor propertyDescriptor
* @param clazz class to test assignability
* @return true if the list associated with the propertyDescriptor have a value added of type clazz
*/
public boolean isCollectionMembersAssignableTo(PropertyDescriptor propertyDescriptor, Class<?> clazz) {
public static boolean isCollectionMembersAssignableTo(PropertyDescriptor propertyDescriptor, Class<?> clazz) {
if (SpdxConstantsCompatV2.RDFS_PROP_SEE_ALSO.equals(propertyDescriptor) ||
SpdxConstantsV3.PROP_SEE_ALSO.equals(propertyDescriptor)) {
return String.class.isAssignableFrom(clazz);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ public boolean isPropertyValueAssignableTo(PropertyDescriptor propertyDescriptor

}

public boolean isCollectionMembersAssignableTo(PropertyDescriptor propertyDescriptor, Class<?> clazz) throws InvalidSpdxPropertyException {
public static boolean isCollectionMembersAssignableTo(PropertyDescriptor propertyDescriptor, Class<?> clazz) throws InvalidSpdxPropertyException {
String propertyName = PROPERTY_DESCRIPTOR_TO_VALUE_NAME.get(propertyDescriptor);
if (Objects.isNull(propertyName)) {
throw new InvalidSpdxPropertyException("Invalid property for SPDX listed license:"+propertyDescriptor.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1098,11 +1098,9 @@ public boolean isCollectionMembersAssignableTo(String objectUri, PropertyDescrip
listedLicenseModificationLock.writeLock().unlock();
}
if (isLicenseId) {
LicenseJson license = fetchLicenseJson(id);
return license.isCollectionMembersAssignableTo(propertyDescriptor, clazz);
return LicenseJson.isCollectionMembersAssignableTo(propertyDescriptor, clazz);
} else if (isExceptionId) {
ExceptionJson exc = fetchExceptionJson(id);
return exc.isCollectionMembersAssignableTo(propertyDescriptor, clazz);
return ExceptionJson.isCollectionMembersAssignableTo(propertyDescriptor, clazz);
} else if (Objects.nonNull(crossRef)) {
return crossRef.isCollectionMembersAssignableTo(propertyDescriptor, clazz);
} else {
Expand Down
71 changes: 55 additions & 16 deletions src/test/java/org/spdx/library/ListedLicensesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.spdx.library;

import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.spdx.core.InvalidSPDXAnalysisException;
Expand All @@ -30,6 +31,7 @@
import org.spdx.storage.compatv2.CompatibleModelStoreWrapper;

import junit.framework.TestCase;
import org.spdx.utility.compare.UnitTestHelper;


/**
Expand Down Expand Up @@ -60,15 +62,15 @@ protected void tearDown() throws Exception {
}

/**
* Test method for {@link org.spdx.library.model.compat.v2.compat.v2.license.ListedLicenses#isSpdxListedLicenseId(java.lang.String)}.
* Test method for {@link org.spdx.library.ListedLicenses#isSpdxListedLicenseId(java.lang.String)}.
*/
public void testIsSpdxListedLicenseID() {
assertTrue(ListedLicenses.getListedLicenses().isSpdxListedLicenseId("Apache-2.0"));
}

/**
* Test method for {@link org.spdx.library.model.compat.v2.compat.v2.license.ListedLicenses#getListedLicenseById(java.lang.String)}.
* @throws InvalidSPDXAnalysisException
* Test method for {@link org.spdx.library.ListedLicenses#getListedLicenseById(java.lang.String)}.
* @throws InvalidSPDXAnalysisException on error getting license IDs
*/
public void testGetListedLicenseById() throws InvalidSPDXAnalysisException {
String id = "Apache-2.0";
Expand All @@ -95,7 +97,7 @@ public void testGetLicenseIbyIdLocal() throws InvalidSPDXAnalysisException {
}
}
/**
* Test method for {@link org.spdx.library.model.compat.v2.compat.v2.license.ListedLicenses#getSpdxListedLicenseIds()}.
* Test method for {@link org.spdx.library.ListedLicenses#getSpdxListedLicenseIds()}.
*/
public void testGetSpdxListedLicenseIds() {
List<String> result = ListedLicenses.getListedLicenses().getSpdxListedLicenseIds();
Expand Down Expand Up @@ -133,21 +135,21 @@ public void testGetExceptionByIdLocal() throws InvalidSPDXAnalysisException {
}
}

public void testGetExceptionIds() throws InvalidSPDXAnalysisException {
public void testGetExceptionIds() {
assertTrue(ListedLicenses.getListedLicenses().getSpdxListedExceptionIds().size() >= NUM_3_7_EXCEPTION);
}

public void testListedLicenseIdCaseSensitive() {
String expected = "Apache-2.0";
String lower = expected.toLowerCase();
assertEquals(expected, ListedLicenses.getListedLicenses().listedLicenseIdCaseSensitive(lower).get());
assertEquals(expected, ListedLicenses.getListedLicenses().listedLicenseIdCaseSensitive(lower).orElse(null));
assertFalse(ListedLicenses.getListedLicenses().listedLicenseIdCaseSensitive("NotaLicenseId").isPresent());
}

public void testListedExceptionIdCaseSensitive() {
String expected = "Classpath-exception-2.0";
String lower = expected.toLowerCase();
assertEquals(expected, ListedLicenses.getListedLicenses().listedExceptionIdCaseSensitive(lower).get());
assertEquals(expected, ListedLicenses.getListedLicenses().listedExceptionIdCaseSensitive(lower).orElse(null));
assertFalse(ListedLicenses.getListedLicenses().listedExceptionIdCaseSensitive("NotAnExceptionId").isPresent());
}

Expand All @@ -161,13 +163,50 @@ public void testGetLicenseIdProperty() throws InvalidSPDXAnalysisException {
assertEquals(id, idProp.get());
}

public void testGetExceptionIdProperty() throws InvalidSPDXAnalysisException {
String id = "Classpath-exception-2.0";
org.spdx.library.model.v2.license.ListedLicenseException ex = ListedLicenses.getListedLicenses().getListedExceptionByIdCompatV2(id);
Optional<Object> idProp = ex.getModelStore().getValue(
CompatibleModelStoreWrapper.documentUriIdToUri(ex.getDocumentUri(), id, false), SpdxConstantsCompatV2.PROP_LICENSE_EXCEPTION_ID);
assertTrue(idProp.isPresent());
assertTrue(idProp.get() instanceof String);
assertEquals(id, idProp.get());
}
public void testGetExceptionIdProperty() throws InvalidSPDXAnalysisException {
String id = "Classpath-exception-2.0";
org.spdx.library.model.v2.license.ListedLicenseException ex = ListedLicenses.getListedLicenses().getListedExceptionByIdCompatV2(id);
Optional<Object> idProp = ex.getModelStore().getValue(
CompatibleModelStoreWrapper.documentUriIdToUri(ex.getDocumentUri(), id, false), SpdxConstantsCompatV2.PROP_LICENSE_EXCEPTION_ID);
assertTrue(idProp.isPresent());
assertTrue(idProp.get() instanceof String);
assertEquals(id, idProp.get());
}

public void testGetListedLicenses() throws InvalidSPDXAnalysisException {
Map<String, ListedLicense> retval =ListedLicenses.getListedLicenses().getSpdxListedLicenses();
List<String> ids = ListedLicenses.getListedLicenses().getSpdxListedLicenseIds();
assertEquals(ids.size(), retval.size());
for (String id:ids) {
assertTrue(retval.get(id).getObjectUri().endsWith(id));
}
}

public void testGetListedLicensesCompatV2() throws InvalidSPDXAnalysisException {
Map<String, SpdxListedLicense> retval =ListedLicenses.getListedLicenses().getSpdxListedLicensesCompatV2();
List<String> ids = ListedLicenses.getListedLicenses().getSpdxListedLicenseIds();
assertEquals(ids.size(), retval.size());
for (String id:ids) {
assertEquals(id, retval.get(id).getId());
}
}

public void testGetListedLicenseExceptions() throws InvalidSPDXAnalysisException {
Map<String, ListedLicenseException> retval =ListedLicenses.getListedLicenses().getSpdxListedLicenseExceptions();
List<String> ids = ListedLicenses.getListedLicenses().getSpdxListedExceptionIds();
assertEquals(ids.size(), retval.size());
for (String id:ids) {
assertTrue(retval.get(id).getObjectUri().endsWith(id));
}
}

public void testGetListedLicenseExceptionsCompatV2() throws InvalidSPDXAnalysisException {
Map<String, org.spdx.library.model.v2.license.ListedLicenseException> retval =
ListedLicenses.getListedLicenses().getSpdxListedLicenseExceptionsCompatV2();
List<String> ids = ListedLicenses.getListedLicenses().getSpdxListedExceptionIds();
assertEquals(ids.size(), retval.size());
for (String id:ids) {
assertEquals(id, retval.get(id).getId());
}
}
}

0 comments on commit 77f3f78

Please sign in to comment.