From 1353ae41effb6d705e0957304ff1e05542f7dbba Mon Sep 17 00:00:00 2001 From: Gary O'Neall Date: Tue, 24 Sep 2024 15:59:52 -0700 Subject: [PATCH] Add support for using LicenseExpression in converter (#252) * Add support for using LicenseExpression in converter Adds an option to the Spdx2to3Converter to use simple licensing license expressions instead of the ExpandedLicensing fully modelled license expressions Also includes a fix for #250 Signed-off-by: Gary O'Neall * Fix excessive warnings in license store Signed-off-by: Gary O'Neall * Fix typos Signed-off-by: Gary O'Neall --------- Signed-off-by: Gary O'Neall --- .../org/spdx/library/LicenseInfoFactory.java | 9 + .../java/org/spdx/library/ListedLicenses.java | 9 + .../org/spdx/library/ModelCopyManager.java | 2 +- .../library/conversion/Spdx2to3Converter.java | 154 +++++++++++++++- .../listedlicense/IListedLicenseStore.java | 8 + .../listedlicense/LicenseCreationInfo.java | 1 - .../SpdxListedLicenseModelStore.java | 164 +++++++++++------- .../SpdxV3ListedLicenseModelStore.java | 9 + .../conversion/Spdx2to3ConverterTest.java | 102 ++++++++--- 9 files changed, 358 insertions(+), 100 deletions(-) diff --git a/src/main/java/org/spdx/library/LicenseInfoFactory.java b/src/main/java/org/spdx/library/LicenseInfoFactory.java index e2d09f86..56e431dd 100644 --- a/src/main/java/org/spdx/library/LicenseInfoFactory.java +++ b/src/main/java/org/spdx/library/LicenseInfoFactory.java @@ -32,6 +32,7 @@ import org.spdx.library.model.v2.license.InvalidLicenseStringException; import org.spdx.library.model.v2.license.LicenseParserException; import org.spdx.library.model.v2.license.SpdxListedLicense; +import org.spdx.library.model.v3_0_1.core.CreationInfo; import org.spdx.library.model.v3_0_1.core.DictionaryEntry; import org.spdx.library.model.v3_0_1.expandedlicensing.ListedLicense; import org.spdx.library.model.v3_0_1.expandedlicensing.ListedLicenseException; @@ -263,5 +264,13 @@ public static Optional listedLicenseIdCaseSensitive(String licenseId) { public static Optional listedExceptionIdCaseSensitive(String exceptionId) { return ListedLicenses.getListedLicenses().listedExceptionIdCaseSensitive(exceptionId); } + + /** + * @return the CreationInfo used for all SPDX listed licenses and listed exceptions + * @throws InvalidSPDXAnalysisException on error inflating the creation info + */ + public static CreationInfo getListedLicenseCreationInfo() throws InvalidSPDXAnalysisException { + return ListedLicenses.getListedLicenses().getListedLicenseCreationInfo(); + } } diff --git a/src/main/java/org/spdx/library/ListedLicenses.java b/src/main/java/org/spdx/library/ListedLicenses.java index 62677796..de3069a2 100644 --- a/src/main/java/org/spdx/library/ListedLicenses.java +++ b/src/main/java/org/spdx/library/ListedLicenses.java @@ -33,6 +33,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.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; import org.spdx.storage.IModelStore; @@ -303,4 +304,12 @@ public IModelStore getLicenseModelStoreCompatV2() { return this.licenseStoreV2; } + /** + * @return the CreationInfo used for all SPDX listed licenses and listed exceptions + * @throws InvalidSPDXAnalysisException on error inflating the creation info + */ + public CreationInfo getListedLicenseCreationInfo() throws InvalidSPDXAnalysisException { + return licenseStoreV3.getListedLicenseCreationInfo(); + } + } \ No newline at end of file diff --git a/src/main/java/org/spdx/library/ModelCopyManager.java b/src/main/java/org/spdx/library/ModelCopyManager.java index a7c0b2c0..4fb03354 100644 --- a/src/main/java/org/spdx/library/ModelCopyManager.java +++ b/src/main/java/org/spdx/library/ModelCopyManager.java @@ -196,7 +196,7 @@ public boolean canConvert(String fromSpecVersion, } if (SpdxConstantsV3.SpdxMajorVersion.VERSION_2.equals(fromMajorVersion) && SpdxConstantsV3.SpdxMajorVersion.VERSION_3.equals(toMajorVersion)) { - retval = new Spdx2to3Converter(toStore, this, null, toSpecVersion, null); + retval = new Spdx2to3Converter(toStore, this, null, toSpecVersion, null, true); //TODO: Add a creation info and uri prefix ISpdxConverter previous = toVersionMap.putIfAbsent(toMajorVersion, retval); if (Objects.nonNull(previous)) { diff --git a/src/main/java/org/spdx/library/conversion/Spdx2to3Converter.java b/src/main/java/org/spdx/library/conversion/Spdx2to3Converter.java index a16d2a98..2a37d56f 100644 --- a/src/main/java/org/spdx/library/conversion/Spdx2to3Converter.java +++ b/src/main/java/org/spdx/library/conversion/Spdx2to3Converter.java @@ -21,10 +21,12 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -45,6 +47,7 @@ import org.spdx.library.model.v3_0_1.core.CreationInfo; import org.spdx.library.model.v3_0_1.core.Element; import org.spdx.library.model.v3_0_1.core.ExternalElement; +import org.spdx.library.model.v3_0_1.core.ExternalIdentifier; import org.spdx.library.model.v3_0_1.core.ExternalIdentifierType; import org.spdx.library.model.v3_0_1.core.ExternalMap; import org.spdx.library.model.v3_0_1.core.ExternalRefType; @@ -79,6 +82,7 @@ import org.spdx.library.model.v3_0_1.expandedlicensing.OrLaterOperator; import org.spdx.library.model.v3_0_1.expandedlicensing.WithAdditionOperator; import org.spdx.library.model.v3_0_1.simplelicensing.AnyLicenseInfo; +import org.spdx.library.model.v3_0_1.simplelicensing.LicenseExpression; import org.spdx.library.model.v3_0_1.software.ContentIdentifierType; import org.spdx.library.model.v3_0_1.software.Snippet; import org.spdx.library.model.v3_0_1.software.SoftwareArtifact; @@ -298,6 +302,8 @@ public class Spdx2to3Converter implements ISpdxConverter { private int documentIndex = 0; + private boolean complexLicenses = false; + /** * @param creationInfoV2 SPDX Spec version 2 creation info * @param modelStore modelStore to store the CreationInfo @@ -416,11 +422,25 @@ public static Agent stringToAgent(String spdx2personOrgString, CreationInfo crea */ public Spdx2to3Converter(IModelStore toModelStore, IModelCopyManager copyManager, CreationInfo defaultCreationInfo, String toSpecVersion, String defaultUriPrefix) { + this(toModelStore, copyManager, defaultCreationInfo, toSpecVersion, defaultUriPrefix, true); + } + + /** + * @param toModelStore modelStore to store any converted elements to + * @param copyManager Copy manager to use for the conversion + * @param defaultCreationInfo creationInfo to use for created SPDX elements + * @param toSpecVersion specific spec version to convert to + * @param defaultUriPrefix URI prefix to use when creating new elements + * @param complexLicenses if true, copy listed license information into the toModelStore and use the ExpandedLicenses otherwise use license expression strings + */ + public Spdx2to3Converter(IModelStore toModelStore, IModelCopyManager copyManager, CreationInfo defaultCreationInfo, + String toSpecVersion, String defaultUriPrefix, boolean complexLicenses) { this.toModelStore = toModelStore; this.defaultCreationInfo = defaultCreationInfo; this.toSpecVersion = toSpecVersion; this.defaultUriPrefix = defaultUriPrefix; this.copyManager = copyManager; + this.complexLicenses = complexLicenses; } /** @@ -431,6 +451,81 @@ public boolean alreadyCopied(String fromObjectUri) { return this.alreadyConverted.containsKey(fromObjectUri); } + /** + * @param spdx2CreatorInfo SPDX 2 creation information + * @param spdx3CreationInfo SPDX 3 creation information + * @return true of the values of the SPDX 2 creation information are equivalent to the SPDX 3 creation information + * @throws InvalidSPDXAnalysisException on error fetching model data + */ + private boolean equivalentCreationInfo(SpdxCreatorInformation spdx2CreatorInfo, + CreationInfo spdx3CreationInfo) throws InvalidSPDXAnalysisException { + if (!Objects.equals(spdx2CreatorInfo.getCreated(), spdx3CreationInfo.getCreated())) { + return false; + } + List tools = spdx3CreationInfo.getCreatedUsings().stream().collect(Collectors.toList()); + List agents = spdx3CreationInfo.getCreatedBys().stream().collect(Collectors.toList()); + for (String creator:spdx2CreatorInfo.getCreators()) { + if (creator.startsWith(SpdxConstantsCompatV2.CREATOR_PREFIX_TOOL)) { + String toolName = creator.substring(SpdxConstantsCompatV2.CREATOR_PREFIX_TOOL.length()).trim(); + boolean found = false; + for (Tool tool:tools) { + if (tool.getName().isPresent() && tool.getName().get().equals(toolName)) { + found = true; + break; + } + } + if (!found) { + return false; + } + } else { + // look for matching agents + String name = creator; + String type = SpdxConstantsV3.CORE_AGENT; + String email = null; + Matcher matcher = SPDX_2_CREATOR_PATTERN.matcher(creator); + if (matcher.matches()) { + if (matcher.group(1).trim().equals("Person")) { + type = SpdxConstantsV3.CORE_PERSON; + } else if (matcher.group(1).trim().equals("Organization")) { + type = SpdxConstantsV3.CORE_ORGANIZATION; + } // otherwise it is just the default AGENT + if (matcher.groupCount() > 1) { + name = matcher.group(2).trim(); + } else { + name = "[MISSING]"; + } + if (matcher.groupCount() > 3) { + email = matcher.group(4); + } + } + boolean found = false; + for (Agent agent:agents) { + if (agent.getType().equals(type) && + agent.getName().isPresent() && agent.getName().get().equals(name)) { + if (Objects.nonNull(email)) { + boolean foundEmail = false; + for (ExternalIdentifier ei:agent.getExternalIdentifiers()) { + if (ExternalIdentifierType.EMAIL.equals(ei.getExternalIdentifierType()) && + email.equals(ei.getIdentifier())) { + foundEmail = true; + break; + } + } + if (foundEmail) { + found = true; + break; + } + } + } + } + if (!found) { + return false; + } + } + } + return true; + } + /** * Coy all element properties from the SPDX spec version 2 element to the SPDX version 3 element * @param fromElement SPDX spec version 2 SpdxElement @@ -585,7 +680,9 @@ public SpdxDocument convertAndStore(org.spdx.library.model.v2.SpdxDocument fromD toDoc.getNamespaceMaps().add(convertAndStore(externalDocRef, toDoc.getSpdxImports())); } convertElementProperties(fromDoc, toDoc); - toDoc.setCreationInfo(convertCreationInfo(fromDoc.getCreationInfo(), this.toModelStore, this.defaultUriPrefix)); + if (!equivalentCreationInfo(fromDoc.getCreationInfo(), defaultCreationInfo)) { + toDoc.setCreationInfo(convertCreationInfo(fromDoc.getCreationInfo(), this.toModelStore, this.defaultUriPrefix)); + } toDoc.setDataLicense(convertAndStore(fromDoc.getDataLicense())); toDoc.getRootElements().addAll(fromDoc.getDocumentDescribes().stream().map(spdxElement -> { try { @@ -601,7 +698,7 @@ public SpdxDocument convertAndStore(org.spdx.library.model.v2.SpdxDocument fromD } return toDoc; } - + /** * Converts the externalDocRef to a NamespaceMap and store the NamespaceMap. * The document information is also retained in the externalDocRefMap such that any subsequent @@ -765,8 +862,10 @@ public ListedLicense convertAndStore(org.spdx.library.model.v2.license.SpdxListe String licenseId = SpdxListedLicenseModelStore.objectUriToLicenseOrExceptionId(fromSpdxListedLicense.getObjectUri()); if (ListedLicenses.getListedLicenses().isSpdxListedLicenseId(licenseId)) { ListedLicense retval = ListedLicenses.getListedLicenses().getListedLicenseById(licenseId); - copyManager.copy(toModelStore, fromSpdxListedLicense.getObjectUri(), retval.getModelStore(), - fromSpdxListedLicense.getObjectUri(), toSpecVersion, null); + if (complexLicenses) { + copyManager.copy(toModelStore, fromSpdxListedLicense.getObjectUri(), retval.getModelStore(), + fromSpdxListedLicense.getObjectUri(), toSpecVersion, null); + } return retval; } ListedLicense toListedLicense = (ListedLicense)SpdxModelClassFactoryV3.getModelObject(toModelStore, @@ -880,8 +979,10 @@ public ListedLicenseException convertAndStore(org.spdx.library.model.v2.license. String exceptionId = SpdxListedLicenseModelStore.objectUriToLicenseOrExceptionId(fromException.getObjectUri()); if (ListedLicenses.getListedLicenses().isSpdxListedExceptionId(exceptionId)) { ListedLicenseException retval = ListedLicenses.getListedLicenses().getListedExceptionById(exceptionId); - copyManager.copy(toModelStore, fromException.getObjectUri(), retval.getModelStore(), - fromException.getObjectUri(), toSpecVersion, null); + if (complexLicenses) { + copyManager.copy(toModelStore, fromException.getObjectUri(), retval.getModelStore(), + fromException.getObjectUri(), toSpecVersion, null); + } return retval; } ListedLicenseException toListedException = (ListedLicenseException)SpdxModelClassFactoryV3.getModelObject(toModelStore, @@ -894,14 +995,51 @@ public ListedLicenseException convertAndStore(org.spdx.library.model.v2.license. return toListedException; } + /** + * Converts an SPDX spec version 2 SPDX AnyLicenseIfno to an SPDX spec version 3 LicenseExpression + * @param fromLicense an SPDX spec version 2 AnyLicenseInfo + * @return an SPDX spec version 3 LicenseExpression + * @throws InvalidSPDXAnalysisException on any errors converting + */ + public LicenseExpression convertToLicenseExpression(org.spdx.library.model.v2.license.AnyLicenseInfo fromLicense) throws InvalidSPDXAnalysisException { + Optional existing = getExistingObject(fromLicense.getObjectUri(), SpdxConstantsV3.SIMPLE_LICENSING_LICENSE_EXPRESSION); + if (existing.isPresent()) { + return (LicenseExpression)existing.get(); + } + String toObjectUri = defaultUriPrefix + toModelStore.getNextId(IdType.SpdxId); + String existingUri = this.alreadyConverted.putIfAbsent(fromLicense.getObjectUri(), toObjectUri); + if (Objects.nonNull(existingUri)) { + // small window if conversion occurred since the last check already converted + return (LicenseExpression)getExistingObject(fromLicense.getObjectUri(), SpdxConstantsV3.SIMPLE_LICENSING_LICENSE_EXPRESSION).get(); + } + LicenseExpression licenseExpression = (LicenseExpression)SpdxModelClassFactoryV3.getModelObject(toModelStore, + toObjectUri, SpdxConstantsV3.SIMPLE_LICENSING_LICENSE_EXPRESSION, copyManager, true, defaultUriPrefix); + licenseExpression.setCreationInfo(defaultCreationInfo); + String expression = fromLicense.toString(); + licenseExpression.setLicenseExpression(expression); + StringTokenizer tokenizer = new StringTokenizer(expression, "() "); + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken().trim(); + if (token.startsWith(SpdxConstantsCompatV2.NON_STD_LICENSE_ID_PRENUM)) { + licenseExpression.getCustomIdToUris().add(licenseExpression.createDictionaryEntry(toModelStore.getNextId(IdType.Anonymous)) + .setKey(token) + .setValue(defaultUriPrefix + token) + .build()); + } + } + return licenseExpression; + } + /** * Converts an SPDX spec version 2 SPDX AnyLicenseIfno to an SPDX spec version 3 SPDX AnyLicenseIfno and store the result - * @param fromLicense an SPDX spec version 2 AnyLicenseIfno + * @param fromLicense an SPDX spec version 2 AnyLicenseInfo * @return an SPDX spec version 3 AnyLicenseIfno * @throws InvalidSPDXAnalysisException on any errors converting */ public AnyLicenseInfo convertAndStore(org.spdx.library.model.v2.license.AnyLicenseInfo fromLicense) throws InvalidSPDXAnalysisException { - if (fromLicense instanceof org.spdx.library.model.v2.license.ConjunctiveLicenseSet) { + if (!complexLicenses) { + return convertToLicenseExpression(fromLicense); + } else if (fromLicense instanceof org.spdx.library.model.v2.license.ConjunctiveLicenseSet) { return convertAndStore((org.spdx.library.model.v2.license.ConjunctiveLicenseSet)fromLicense); } else if (fromLicense instanceof org.spdx.library.model.v2.license.DisjunctiveLicenseSet) { return convertAndStore((org.spdx.library.model.v2.license.DisjunctiveLicenseSet)fromLicense); diff --git a/src/main/java/org/spdx/storage/listedlicense/IListedLicenseStore.java b/src/main/java/org/spdx/storage/listedlicense/IListedLicenseStore.java index bf58ce99..e3f3900a 100644 --- a/src/main/java/org/spdx/storage/listedlicense/IListedLicenseStore.java +++ b/src/main/java/org/spdx/storage/listedlicense/IListedLicenseStore.java @@ -20,6 +20,8 @@ import java.util.List; import java.util.Optional; +import org.spdx.core.InvalidSPDXAnalysisException; +import org.spdx.library.model.v3_0_1.core.CreationInfo; import org.spdx.storage.IModelStore; /** @@ -71,4 +73,10 @@ public interface IListedLicenseStore extends IModelStore { */ Optional listedExceptionIdCaseSensitive(String exceptionId); + /** + * @return the CreationInfo used for all SPDX listed licenses and listed exceptions + * @throws InvalidSPDXAnalysisException on error inflating the creation info + */ + CreationInfo getListedLicenseCreationInfo() throws InvalidSPDXAnalysisException; + } diff --git a/src/main/java/org/spdx/storage/listedlicense/LicenseCreationInfo.java b/src/main/java/org/spdx/storage/listedlicense/LicenseCreationInfo.java index 9d0a2752..44cc24a0 100644 --- a/src/main/java/org/spdx/storage/listedlicense/LicenseCreationInfo.java +++ b/src/main/java/org/spdx/storage/listedlicense/LicenseCreationInfo.java @@ -158,5 +158,4 @@ public boolean isPropertyValueAssignableTo( SpdxConstantsV3.PROP_SPEC_VERSION.equals(propertyDescriptor) || SpdxConstantsV3.PROP_CREATED.equals(propertyDescriptor)); } - } diff --git a/src/main/java/org/spdx/storage/listedlicense/SpdxListedLicenseModelStore.java b/src/main/java/org/spdx/storage/listedlicense/SpdxListedLicenseModelStore.java index 046b4c57..c74ada9e 100644 --- a/src/main/java/org/spdx/storage/listedlicense/SpdxListedLicenseModelStore.java +++ b/src/main/java/org/spdx/storage/listedlicense/SpdxListedLicenseModelStore.java @@ -44,10 +44,12 @@ import org.spdx.core.InvalidSPDXAnalysisException; import org.spdx.core.SpdxIdNotFoundException; import org.spdx.core.TypedValue; +import org.spdx.library.SpdxModelFactory; import org.spdx.library.model.v2.ModelObjectV2; import org.spdx.library.model.v2.SpdxConstantsCompatV2; import org.spdx.library.model.v2.license.SpdxListedLicenseException; import org.spdx.library.model.v3_0_1.SpdxConstantsV3; +import org.spdx.library.model.v3_0_1.core.CreationInfo; import org.spdx.storage.PropertyDescriptor; import com.google.gson.Gson; @@ -301,6 +303,11 @@ public void create(TypedValue typedValue) throws InvalidSPDXAnalysisException { */ @Override public List getPropertyValueDescriptors(String objectUri) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + return LicenseCreationInfo.ALL_PROPERTY_DESCRIPTORS; + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + return LicenseCreatorAgent.ALL_PROPERTY_DESCRIPTORS; + } String id = objectUriToId(objectUri); listedLicenseModificationLock.readLock().lock(); try { @@ -314,10 +321,6 @@ public List getPropertyValueDescriptors(String objectUri) th } else if (crossRefs.containsKey(id)) { return crossRefs.get(id).getPropertyValueDescriptors(); // Currently, there is no SPDX 3 support for cross refs - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - return LicenseCreationInfo.ALL_PROPERTY_DESCRIPTORS; - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - return LicenseCreatorAgent.ALL_PROPERTY_DESCRIPTORS; } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID. crossRef ID nor a listed exception ID"); @@ -475,6 +478,13 @@ private ExceptionJson fetchExceptionJson(String idCaseInsensitive) throws Invali */ @Override public void setValue(String objectUri, PropertyDescriptor propertyDescriptor, Object value) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + logger.warn("Ignoring the setting of "+propertyDescriptor.getName()+" for license list creation info"); + return; + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + logger.warn("Ignoring the setting of "+propertyDescriptor.getName()+" for license list creator info"); + return; + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -499,10 +509,6 @@ public void setValue(String objectUri, PropertyDescriptor propertyDescriptor, Ob exc.setPrimativeValue(propertyDescriptor, value); } else if (Objects.nonNull(crossRef)) { crossRef.setPrimativeValue(propertyDescriptor, value); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - logger.warn("Ignoring the setting of "+propertyDescriptor.getName()+" for license list creation info"); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - logger.warn("Ignoring the setting of "+propertyDescriptor.getName()+" for license list creator info"); } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -514,6 +520,13 @@ public void setValue(String objectUri, PropertyDescriptor propertyDescriptor, Ob */ @Override public void clearValueCollection(String objectUri, PropertyDescriptor propertyDescriptor) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + logger.warn("Ignoring the clearing of collection for license list creation info"); + return; + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + logger.warn("Ignoring the clearing of collection for license list creator"); + return; + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -538,10 +551,6 @@ public void clearValueCollection(String objectUri, PropertyDescriptor propertyDe exc.clearPropertyValueList(propertyDescriptor); } else if (Objects.nonNull(crossRef)) { crossRef.clearPropertyValueList(propertyDescriptor); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - logger.warn("Ignoring the clearing of collection for license list creation info"); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - logger.warn("Ignoring the clearing of collection for license list creator"); } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -553,6 +562,13 @@ public void clearValueCollection(String objectUri, PropertyDescriptor propertyDe */ @Override public boolean addValueToCollection(String objectUri, PropertyDescriptor propertyDescriptor, Object value) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + logger.warn("Ignoring the adding to collection for license list creation info"); + return false; + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + logger.warn("Ignoring the adding to collection for license list creator"); + return false; + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -595,12 +611,6 @@ public boolean addValueToCollection(String objectUri, PropertyDescriptor propert return exc.addPrimitiveValueToList(propertyDescriptor, value); } else if (Objects.nonNull(crossRef)) { return crossRef.addPrimitiveValueToList(propertyDescriptor, value); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - logger.warn("Ignoring the adding to collection for license list creation info"); - return false; - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - logger.warn("Ignoring the adding to collection for license list creator"); - return false; } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -610,6 +620,13 @@ public boolean addValueToCollection(String objectUri, PropertyDescriptor propert @Override public boolean removeValueFromCollection(String objectUri, PropertyDescriptor propertyDescriptor, Object value) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + logger.warn("Ignoring the removing from collection for license list creation info"); + return false; + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + logger.warn("Ignoring the removing from collection for license list creator"); + return false; + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -652,12 +669,6 @@ public boolean removeValueFromCollection(String objectUri, PropertyDescriptor pr return exc.removePrimitiveValueToList(propertyDescriptor, value); } else if (Objects.nonNull(crossRef)) { return crossRef.removePrimitiveValueToList(propertyDescriptor, value); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - logger.warn("Ignoring the removing from collection for license list creation info"); - return false; - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - logger.warn("Ignoring the removing from collection for license list creator"); - return false; } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -670,6 +681,11 @@ public boolean removeValueFromCollection(String objectUri, PropertyDescriptor pr @SuppressWarnings("unchecked") @Override public Iterator listValues(String objectUri, PropertyDescriptor propertyDescriptor) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + return ((List)(List)licenseCreationInfo.getValueList(propertyDescriptor)).iterator(); + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + return ((List)(List)licenseCreator.getValueList(propertyDescriptor)).iterator(); + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -741,10 +757,6 @@ public Object next() { return ((List)(List)exc.getValueList(propertyDescriptor)).iterator(); } else if (Objects.nonNull(crossRef)) { return ((List)(List)crossRef.getValueList(propertyDescriptor)).iterator(); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - return ((List)(List)licenseCreationInfo.getValueList(propertyDescriptor)).iterator(); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - return ((List)(List)licenseCreator.getValueList(propertyDescriptor)).iterator(); } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -756,6 +768,11 @@ public Object next() { */ @Override public Optional getValue(String objectUri, PropertyDescriptor propertyDescriptor) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + return Optional.ofNullable(licenseCreationInfo.getValue(propertyDescriptor)); + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + return Optional.ofNullable(licenseCreator.getValue(propertyDescriptor)); + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -782,10 +799,6 @@ public Optional getValue(String objectUri, PropertyDescriptor propertyDe return Optional.ofNullable(exc.getValue(propertyDescriptor)); } else if (Objects.nonNull(crossRef)) { return Optional.ofNullable(crossRef.getValue(propertyDescriptor)); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - return Optional.ofNullable(licenseCreationInfo.getValue(propertyDescriptor)); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - return Optional.ofNullable(licenseCreator.getValue(propertyDescriptor)); } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -887,6 +900,11 @@ public boolean isSpdxListedExceptionId(String listedLicenseDocumentUri, String e public Optional getTypedValue(String objectUri) throws InvalidSPDXAnalysisException { //NOTE: We only return the SPDX 3.0 version of the typed value, SPDX 2.X versions are also supported // but there is no API to specify the version of the typedValue + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + return Optional.of(licenseCreationInfo.getTypedValue()); + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + return Optional.of(licenseCreator.getTypedValue()); + } String id = objectUriToId(objectUri); listedLicenseModificationLock.readLock().lock(); try { @@ -897,11 +915,7 @@ public Optional getTypedValue(String objectUri) throws InvalidSPDXAn } else if (crossRefs.containsKey(id)) { // Cross refs are only supported in SPDX version 2.X return Optional.of(new TypedValue(objectUri, SpdxConstantsCompatV2.CLASS_CROSS_REF, ModelObjectV2.LATEST_SPDX_2_VERSION)); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - return Optional.of(licenseCreationInfo.getTypedValue()); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - return Optional.of(licenseCreator.getTypedValue()); - } else { + } else { return Optional.empty(); } } finally { @@ -911,6 +925,13 @@ public Optional getTypedValue(String objectUri) throws InvalidSPDXAn @Override public void removeProperty(String objectUri, PropertyDescriptor propertyDescriptor) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + logger.warn("Ignoring remove property "+propertyDescriptor.getName()+" for license list creation info"); + return; + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + logger.warn("Ignoring remove property "+propertyDescriptor.getName()+" for license list creator"); + return; + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -935,10 +956,6 @@ public void removeProperty(String objectUri, PropertyDescriptor propertyDescript exc.removeProperty(propertyDescriptor); } else if (Objects.nonNull(crossRef)) { crossRef.removeProperty(propertyDescriptor); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - logger.warn("Ignoring remove property "+propertyDescriptor.getName()+" for license list creation info"); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - logger.warn("Ignoring remove property "+propertyDescriptor.getName()+" for license list creator"); } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -994,6 +1011,11 @@ public Stream getAllItems(String documentUri, @Nullable String typeF @SuppressWarnings("unchecked") @Override public int collectionSize(String objectUri, PropertyDescriptor propertyDescriptor) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + return ((List)(List)licenseCreationInfo.getValueList(propertyDescriptor)).size(); + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + return ((List)(List)licenseCreator.getValueList(propertyDescriptor)).size(); + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -1018,10 +1040,6 @@ public int collectionSize(String objectUri, PropertyDescriptor propertyDescripto return ((List)(List)exc.getValueList(propertyDescriptor)).size(); } else if (Objects.nonNull(crossRef)) { return ((List)(List)crossRef.getValueList(propertyDescriptor)).size(); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - return ((List)(List)licenseCreationInfo.getValueList(propertyDescriptor)).size(); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - return ((List)(List)licenseCreator.getValueList(propertyDescriptor)).size(); } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -1032,6 +1050,11 @@ public int collectionSize(String objectUri, PropertyDescriptor propertyDescripto @Override public boolean collectionContains(String objectUri, PropertyDescriptor propertyDescriptor, Object value) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + return ((List)(List)licenseCreationInfo.getValueList(propertyDescriptor)).contains(value); + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + return ((List)(List)licenseCreator.getValueList(propertyDescriptor)).contains(value); + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -1066,10 +1089,6 @@ public boolean collectionContains(String objectUri, PropertyDescriptor propertyD return ((List)(List)exc.getValueList(propertyDescriptor)).contains(value); } else if (Objects.nonNull(crossRef)) { return ((List)(List)crossRef.getValueList(propertyDescriptor)).contains(value); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - return ((List)(List)licenseCreationInfo.getValueList(propertyDescriptor)).contains(value); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - return ((List)(List)licenseCreator.getValueList(propertyDescriptor)).contains(value); } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -1079,6 +1098,11 @@ public boolean collectionContains(String objectUri, PropertyDescriptor propertyD @Override public boolean isCollectionMembersAssignableTo(String objectUri, PropertyDescriptor propertyDescriptor, Class clazz) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + return licenseCreationInfo.isCollectionMembersAssignableTo(propertyDescriptor, clazz); + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + return licenseCreator.isCollectionMembersAssignableTo(propertyDescriptor, clazz); + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -1103,10 +1127,6 @@ public boolean isCollectionMembersAssignableTo(String objectUri, PropertyDescrip return exc.isCollectionMembersAssignableTo(propertyDescriptor, clazz); } else if (Objects.nonNull(crossRef)) { return crossRef.isCollectionMembersAssignableTo(propertyDescriptor, clazz); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - return licenseCreationInfo.isCollectionMembersAssignableTo(propertyDescriptor, clazz); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - return licenseCreator.isCollectionMembersAssignableTo(propertyDescriptor, clazz); } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -1117,6 +1137,11 @@ public boolean isCollectionMembersAssignableTo(String objectUri, PropertyDescrip public boolean isPropertyValueAssignableTo(String objectUri, PropertyDescriptor propertyDescriptor, Class clazz, String specVersion) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + return licenseCreationInfo.isPropertyValueAssignableTo(propertyDescriptor, clazz); + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + return licenseCreator.isPropertyValueAssignableTo(propertyDescriptor, clazz); + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -1141,10 +1166,6 @@ public boolean isPropertyValueAssignableTo(String objectUri, PropertyDescriptor return exc.isPropertyValueAssignableTo(propertyDescriptor, clazz); } else if (Objects.nonNull(crossRef)) { return crossRef.isPropertyValueAssignableTo(propertyDescriptor, clazz); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - return licenseCreationInfo.isPropertyValueAssignableTo(propertyDescriptor, clazz); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - return licenseCreator.isPropertyValueAssignableTo(propertyDescriptor, clazz); } else { logger.error("ID "+id+" is not a listed license ID, CrossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, CrossRef ID nor a listed exception ID"); @@ -1154,6 +1175,11 @@ public boolean isPropertyValueAssignableTo(String objectUri, PropertyDescriptor @Override public boolean isCollectionProperty(String objectUri, PropertyDescriptor propertyDescriptor) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + return this.licenseCreationInfo.isCollectionProperty(propertyDescriptor); + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + return licenseCreator.isCollectionProperty(propertyDescriptor); + } String id = objectUriToId(objectUri); boolean isLicenseId = false; boolean isExceptionId = false; @@ -1178,10 +1204,6 @@ public boolean isCollectionProperty(String objectUri, PropertyDescriptor propert return exc.isCollectionProperty(propertyDescriptor); } else if (Objects.nonNull(crossRef)) { return crossRef.isCollectionProperty(propertyDescriptor.getName()); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - return this.licenseCreationInfo.isCollectionProperty(propertyDescriptor); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - return licenseCreator.isCollectionProperty(propertyDescriptor); } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -1256,6 +1278,13 @@ public Optional getCaseSensisitiveId(String documentUri, String caseInse @Override public void delete(String objectUri) throws InvalidSPDXAnalysisException { + if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { + logger.warn("Ignoring the removal of the creation info for the license list"); + return; + } else if (licenseCreator.getObjectUri().equals(objectUri)) { + logger.warn("Ignoring the removal of the creator for the license list"); + return; + } String id = objectUriToId(objectUri); listedLicenseModificationLock.writeLock().lock(); try { @@ -1267,10 +1296,6 @@ public void delete(String objectUri) throws InvalidSPDXAnalysisException { this.exceptionIds.remove(id.toLowerCase()); } else if (crossRefs.containsKey(id)) { this.crossRefs.remove(id); - } else if (LicenseCreationInfo.CREATION_INFO_URI.equals(objectUri)) { - logger.warn("Ignoring the removal of the creation info for the license list"); - } else if (licenseCreator.getObjectUri().equals(objectUri)) { - logger.warn("Ignoring the removal of the creator for the license list"); } else { logger.error("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); throw new SpdxIdNotFoundException("ID "+id+" is not a listed license ID, crossRef ID nor a listed exception ID"); @@ -1280,6 +1305,15 @@ public void delete(String objectUri) throws InvalidSPDXAnalysisException { } } + /** + * @return the CreationInfo used for all SPDX listed licenses and listed exceptions + * @throws InvalidSPDXAnalysisException on error inflating the CreationInfo + */ + public CreationInfo getListedLicenseCreationInfo() throws InvalidSPDXAnalysisException { + return (CreationInfo) SpdxModelFactory.inflateModelObject(this, LicenseCreationInfo.CREATION_INFO_URI, + SpdxConstantsV3.CORE_CREATION_INFO, null, SpdxConstantsV3.MODEL_SPEC_VERSION, false, null); + } + @Override public void close() throws Exception { // Nothing to do for the either the in-memory or the web store diff --git a/src/main/java/org/spdx/storage/listedlicense/SpdxV3ListedLicenseModelStore.java b/src/main/java/org/spdx/storage/listedlicense/SpdxV3ListedLicenseModelStore.java index 4a8dcaaf..eb323d44 100644 --- a/src/main/java/org/spdx/storage/listedlicense/SpdxV3ListedLicenseModelStore.java +++ b/src/main/java/org/spdx/storage/listedlicense/SpdxV3ListedLicenseModelStore.java @@ -29,6 +29,7 @@ import org.spdx.core.TypedValue; import org.spdx.library.model.v2.SpdxConstantsCompatV2; import org.spdx.library.model.v3_0_1.SpdxConstantsV3; +import org.spdx.library.model.v3_0_1.core.CreationInfo; import org.spdx.storage.IModelStore; import org.spdx.storage.PropertyDescriptor; @@ -386,4 +387,12 @@ public void delete(String objectUri) throws InvalidSPDXAnalysisException { public boolean isAnon(String objectUri) { return baseStore.isAnon(objectUri); } + + /** + * @return the CreationInfo used for all SPDX listed licenses and listed exceptions + * @throws InvalidSPDXAnalysisException on error inflating the creation info + */ + public CreationInfo getListedLicenseCreationInfo() throws InvalidSPDXAnalysisException { + return baseStore.getListedLicenseCreationInfo(); + } } diff --git a/src/test/java/org/spdx/library/conversion/Spdx2to3ConverterTest.java b/src/test/java/org/spdx/library/conversion/Spdx2to3ConverterTest.java index 14c28bca..30cbbe2c 100644 --- a/src/test/java/org/spdx/library/conversion/Spdx2to3ConverterTest.java +++ b/src/test/java/org/spdx/library/conversion/Spdx2to3ConverterTest.java @@ -22,7 +22,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -45,6 +47,7 @@ import org.spdx.library.model.v3_0_1.core.Agent; import org.spdx.library.model.v3_0_1.core.Annotation; import org.spdx.library.model.v3_0_1.core.CreationInfo; +import org.spdx.library.model.v3_0_1.core.DictionaryEntry; import org.spdx.library.model.v3_0_1.core.Element; import org.spdx.library.model.v3_0_1.core.ExternalElement; import org.spdx.library.model.v3_0_1.core.ExternalIdentifier; @@ -78,6 +81,7 @@ import org.spdx.library.model.v3_0_1.expandedlicensing.OrLaterOperator; import org.spdx.library.model.v3_0_1.expandedlicensing.WithAdditionOperator; import org.spdx.library.model.v3_0_1.simplelicensing.AnyLicenseInfo; +import org.spdx.library.model.v3_0_1.simplelicensing.LicenseExpression; import org.spdx.library.model.v3_0_1.software.Snippet; import org.spdx.library.model.v3_0_1.software.SpdxFile; import org.spdx.library.model.v3_0_1.software.SpdxPackage; @@ -181,7 +185,7 @@ public void testConvertCreationInfo() throws InvalidSPDXAnalysisException { @Test public void testSpdx2to3Converter() { Spdx2to3Converter result = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); assertFalse(result.alreadyCopied(DOCUMENT_URI)); } @@ -198,7 +202,7 @@ public void testAlreadyCopied() throws InvalidSPDXAnalysisException { licV2.setExtractedText("Extracted Text"); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); assertFalse(converter.alreadyCopied(DOCUMENT_URI + "#" + licenseId)); converter.convertAndStore(licV2); assertTrue(converter.alreadyCopied(DOCUMENT_URI + "#" + licenseId)); @@ -257,7 +261,7 @@ public void testExternalElement() throws InvalidSPDXAnalysisException { assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); SpdxDocument result = converter.convertAndStore(doc); List resultRelationships = new ArrayList<>(); @@ -335,7 +339,7 @@ public void testExternalExtractedLicenseInfo() throws InvalidSPDXAnalysisExcepti assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); SpdxDocument result = converter.convertAndStore(doc); List resultRelationships = new ArrayList<>(); @@ -406,7 +410,7 @@ public void TestNoneElement() throws InvalidSPDXAnalysisException { assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); SpdxDocument result = converter.convertAndStore(doc); List resultRelationships = new ArrayList<>(); @@ -447,7 +451,7 @@ public void TestNoAssertionLicense() throws InvalidSPDXAnalysisException { assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); DisjunctiveLicenseSet result = converter.convertAndStore(ors); AnyLicenseInfo[] members = result.getMembers().toArray(new AnyLicenseInfo[result.getMembers().size()]); assertEquals(2, members.length); @@ -482,7 +486,7 @@ public void testGetExistingObject() throws InvalidSPDXAnalysisException { licV2.setExtractedText("Extracted Text"); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); assertFalse(converter.getExistingObject(DOCUMENT_URI + "#" + licenseId, SpdxConstantsV3.EXPANDED_LICENSING_CUSTOM_LICENSE).isPresent()); CustomLicense customLicense = converter.convertAndStore(licV2); @@ -587,7 +591,7 @@ public void testConvertAndStoreSpdxDocument() throws InvalidSPDXAnalysisExceptio assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); SpdxDocument result = converter.convertAndStore(doc); assertEquals(docComment, result.getComment().get()); assertEquals(dataLicenseStr, result.getDataLicense().get().toString()); @@ -677,7 +681,7 @@ public void testConvertAndStoreExternalDocRef() throws InvalidSPDXAnalysisExcept new org.spdx.library.model.v2.ExternalDocumentRef(fromModelStore, DOCUMENT_URI, externalDocumentId, copyManager, true); externalDocRef.setSpdxDocumentNamespace(externalDocumentUri); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); Collection docImports = new ArrayList<>(); NamespaceMap result = converter.convertAndStore(externalDocRef, docImports); assertEquals(externalDocumentId, result.getPrefix()); @@ -741,7 +745,7 @@ public void testConvertAndStoreRelationship() throws InvalidSPDXAnalysisExceptio .build(); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); SpdxPackage packageElement = converter.convertAndStore(pkg); List verify = packageElement.verify(); @@ -887,7 +891,7 @@ public void testConvertAndStoreAnnotation() throws InvalidSPDXAnalysisException assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); SpdxFile file = converter.convertAndStore(spdxFile); Annotation result = converter.convertAndStore(annotation, file); @@ -940,7 +944,7 @@ public void testConvertAndStoreListedLicenseException() throws InvalidSPDXAnalys assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); LicenseAddition result = converter.convertAndStore(licException); assertTrue(result instanceof ListedLicenseException); assertEquals(exceptionComment, result.getComment().get()); @@ -963,7 +967,7 @@ public void testConvertAndStoreElement() throws InvalidSPDXAnalysisException { org.spdx.library.model.v2.ExternalSpdxElement externalElement = new org.spdx.library.model.v2.ExternalSpdxElement(fromModelStore, externalDocumentUri, externalId, copyManager, true); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); Element result = converter.convertAndStore((org.spdx.library.model.v2.SpdxElement)externalElement); assertTrue(result instanceof ExternalElement); List verify = result.verify(); @@ -1088,7 +1092,7 @@ public void testConvertAndStoreHash() throws InvalidSPDXAnalysisException { assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); Hash result = converter.convertAndStore(checksum); assertEquals(checksumAlgorithm.toString(), result.getAlgorithm().toString()); assertEquals(value, result.getHashValue()); @@ -1122,7 +1126,7 @@ public void testConvertAndStoreConjunctiveLicenseSet() throws InvalidSPDXAnalysi assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); ConjunctiveLicenseSet result = converter.convertAndStore(ands); AnyLicenseInfo[] members = result.getMembers().toArray(new AnyLicenseInfo[result.getMembers().size()]); assertEquals(2, members.length); @@ -1170,7 +1174,7 @@ public void testConvertAndStoreDisjunctiveLicenseSet() throws InvalidSPDXAnalysi assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); DisjunctiveLicenseSet result = converter.convertAndStore(ors); AnyLicenseInfo[] members = result.getMembers().toArray(new AnyLicenseInfo[result.getMembers().size()]); assertEquals(2, members.length); @@ -1216,7 +1220,7 @@ public void testConvertAndStoreExtractedLicenseInfo() throws InvalidSPDXAnalysis assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); CustomLicense result = converter.convertAndStore(licV2); assertEquals(extractedLicComment, result.getComment().get()); assertEquals(extractedText, result.getLicenseText()); @@ -1248,7 +1252,7 @@ public void testConvertAndStoreOrLaterOperator() throws InvalidSPDXAnalysisExcep List verify = orLater.verify(); assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); OrLaterOperator result = converter.convertAndStore(orLater); assertEquals(extractedText, result.getSubjectLicense().getLicenseText()); assertEquals(extractedLicName, result.getSubjectLicense().getName().get()); @@ -1295,7 +1299,7 @@ public void testConvertAndStoreSpdxListedLicense() throws InvalidSPDXAnalysisExc assertEquals(1, verify.size()); // deprecated ID causes a warning Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); ListedLicense result = converter.convertAndStore(listedLicense); assertEquals(licenseComment, result.getComment().get()); assertEquals(deprecated, result.getIsDeprecatedLicenseId().get()); @@ -1335,7 +1339,7 @@ public void testConvertAndStoreWithExceptionOperator() throws InvalidSPDXAnalysi List verify = withException.verify(); assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); WithAdditionOperator result = converter.convertAndStore(withException); assertTrue(result.getSubjectExtendableLicense().getObjectUri().endsWith("Apache-2.0")); assertEquals(exceptionText, result.getSubjectAddition().getAdditionText()); @@ -1348,7 +1352,7 @@ public void testConvertAndStoreWithExceptionOperator() throws InvalidSPDXAnalysi @Test public void testConvertAndStoreAnyLicenseInfo() throws InvalidSPDXAnalysisException { Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); // org.spdx.library.model.v2.license.ExtractedLicenseInfo; String extractedText = "Extracted text"; @@ -1524,7 +1528,7 @@ public void testConvertAndStoreSpdxFile() throws InvalidSPDXAnalysisException { assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); SpdxFile result = converter.convertAndStore(spdxFile); List resultRelationships = new ArrayList<>(); SpdxModelFactory.getSpdxObjects(toModelStore, copyManager, SpdxConstantsV3.CORE_RELATIONSHIP, DEFAULT_PREFIX, DEFAULT_PREFIX).forEach(rel -> resultRelationships.add((Relationship)rel)); @@ -1670,7 +1674,7 @@ public void testConvertAndStoreSpdxPackage() throws InvalidSPDXAnalysisException assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); SpdxPackage result = converter.convertAndStore(pkg); List resultRelationships = new ArrayList<>(); SpdxModelFactory.getSpdxObjects(toModelStore, copyManager, SpdxConstantsV3.CORE_RELATIONSHIP, DEFAULT_PREFIX, DEFAULT_PREFIX).forEach(rel -> resultRelationships.add((Relationship)rel)); @@ -1811,7 +1815,7 @@ public void testConvertAndStoreSpdxSnippet() throws InvalidSPDXAnalysisException assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); Snippet result = converter.convertAndStore(snippet); List resultRelationships = new ArrayList<>(); @@ -1889,7 +1893,7 @@ public void testConvertAndStoreLicenseAddition() throws InvalidSPDXAnalysisExcep assertTrue(verify.isEmpty()); Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, - SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX); + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); LicenseAddition result = converter.convertAndStore((org.spdx.library.model.v2.license.LicenseException)licException); assertTrue(result instanceof ListedLicenseException); assertEquals(exceptionComment, result.getComment().get()); @@ -1903,5 +1907,53 @@ public void testConvertAndStoreLicenseAddition() throws InvalidSPDXAnalysisExcep verify = result.verify(); assertTrue(verify.isEmpty()); } + + @Test + public void testConvertToLicenseExpression() throws InvalidSPDXAnalysisException { + String extractedText = "Extracted text1"; + String extractedLicName = "name"; + String extractedText2 = "Extracted text2"; + String extractedLicName2 = "name2"; + String licId1 = fromModelStore.getNextId(IdType.LicenseRef); + String licId2 = fromModelStore.getNextId(IdType.LicenseRef); + org.spdx.library.model.v2.license.ExtractedLicenseInfo lic1 = + new org.spdx.library.model.v2.license.ExtractedLicenseInfo(fromModelStore, DOCUMENT_URI, licId1, + copyManager, true); + lic1.setName(extractedLicName); + lic1.setExtractedText(extractedText); + org.spdx.library.model.v2.license.AnyLicenseInfo lic2 = + LicenseInfoFactory.parseSPDXLicenseStringCompatV2("Apache-2.0", fromModelStore, DOCUMENT_URI, copyManager); + + org.spdx.library.model.v2.license.ConjunctiveLicenseSet ands = + new org.spdx.library.model.v2.license.ConjunctiveLicenseSet(fromModelStore, DOCUMENT_URI, fromModelStore.getNextId(IdType.Anonymous), + copyManager, true); + org.spdx.library.model.v2.license.ExtractedLicenseInfo lic3 = + new org.spdx.library.model.v2.license.ExtractedLicenseInfo(fromModelStore, DOCUMENT_URI, licId2, + copyManager, true); + lic3.setName(extractedLicName2); + lic3.setExtractedText(extractedText2); + ands.addMember(lic1); + ands.addMember(lic2); + ands.addMember(lic3); + List verify = ands.verify(); + assertTrue(verify.isEmpty()); + + Spdx2to3Converter converter = new Spdx2to3Converter(toModelStore, copyManager, defaultCreationInfo, + SpdxModelFactory.getLatestSpecVersion(), DEFAULT_PREFIX, true); + + LicenseExpression result = converter.convertToLicenseExpression(ands); + Map expected = new HashMap<>(); + expected.put(licId1, DEFAULT_PREFIX + licId1); + expected.put(licId2, DEFAULT_PREFIX + licId2); + for (DictionaryEntry entry:result.getCustomIdToUris()) { + String id = entry.getKey(); + String uri = entry.getValue().get(); + assertTrue(expected.containsKey(id)); + assertEquals(expected.get(id), uri); + expected.remove(id); + } + assertTrue(expected.isEmpty()); + assertEquals(ands.toString(), result.getLicenseExpression()); + } }