Skip to content

Commit 3718577

Browse files
committed
Remove any single member license sets from parsed licenses
Fixes #419 Signed-off-by: Gary O'Neall <gary@sourceauditor.com>
1 parent a01329e commit 3718577

4 files changed

Lines changed: 140 additions & 35 deletions

File tree

src/main/java/org/spdx/library/LicenseInfoFactory.java

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
*/
1818
package org.spdx.library;
1919

20-
import java.util.List;
21-
import java.util.Objects;
22-
import java.util.Optional;
20+
import java.util.*;
2321

2422
import javax.annotation.Nullable;
2523

@@ -30,10 +28,13 @@
3028
import org.spdx.core.IModelCopyManager;
3129
import org.spdx.core.InvalidSPDXAnalysisException;
3230
import org.spdx.library.model.v2.license.InvalidLicenseStringException;
31+
import org.spdx.library.model.v2.license.LicenseSet;
3332
import org.spdx.library.model.v2.license.SpdxListedLicense;
3433
import org.spdx.library.model.v3_0_1.SpdxModelClassFactoryV3;
3534
import org.spdx.library.model.v3_0_1.core.CreationInfo;
3635
import org.spdx.library.model.v3_0_1.core.DictionaryEntry;
36+
import org.spdx.library.model.v3_0_1.expandedlicensing.ConjunctiveLicenseSet;
37+
import org.spdx.library.model.v3_0_1.expandedlicensing.DisjunctiveLicenseSet;
3738
import org.spdx.library.model.v3_0_1.expandedlicensing.ListedLicense;
3839
import org.spdx.library.model.v3_0_1.expandedlicensing.ListedLicenseException;
3940
import org.spdx.library.model.v3_0_1.simplelicensing.AnyLicenseInfo;
@@ -96,7 +97,7 @@ public static SpdxListedLicense getListedLicenseByIdCompatV2(String licenseId)th
9697
* @throws DefaultStoreNotInitializedException if the default model store is not initialized
9798
*/
9899
public static org.spdx.library.model.v2.license.AnyLicenseInfo parseSPDXLicenseStringCompatV2(String licenseString, @Nullable IModelStore store,
99-
@Nullable String documentUri, @Nullable IModelCopyManager copyManager) throws InvalidLicenseStringException, DefaultStoreNotInitializedException {
100+
@Nullable String documentUri, @Nullable IModelCopyManager copyManager) throws DefaultStoreNotInitializedException {
100101
if (Objects.isNull(store)) {
101102
store = DefaultModelStore.getDefaultModelStore();
102103
}
@@ -107,8 +108,8 @@ public static org.spdx.library.model.v2.license.AnyLicenseInfo parseSPDXLicenseS
107108
copyManager = DefaultModelStore.getDefaultCopyManager();
108109
}
109110
try {
110-
return LicenseExpressionParser.parseLicenseExpressionCompatV2(licenseString, store, documentUri,
111-
copyManager);
111+
return fixSingleMemberSetsCompatV2(LicenseExpressionParser.parseLicenseExpressionCompatV2(licenseString, store, documentUri,
112+
copyManager));
112113
} catch (LicenseParserException e) {
113114
try {
114115
return new org.spdx.library.model.v2.license.InvalidLicenseExpression(store, documentUri,
@@ -126,7 +127,74 @@ public static org.spdx.library.model.v2.license.AnyLicenseInfo parseSPDXLicenseS
126127
}
127128
}
128129
}
129-
130+
131+
/**
132+
* Fixes any single member license sets found within an AnyLicenseInfo
133+
* @param license any type of license
134+
* @return license with any single member license sets replaced by the single member value
135+
*/
136+
private static AnyLicenseInfo fixSingleMemberSets(AnyLicenseInfo license) throws InvalidSPDXAnalysisException {
137+
Set<AnyLicenseInfo> members = null;
138+
if (license instanceof ConjunctiveLicenseSet) {
139+
members = ((ConjunctiveLicenseSet) license).getMembers();
140+
} else if (license instanceof DisjunctiveLicenseSet) {
141+
members = ((DisjunctiveLicenseSet) license).getMembers();
142+
}
143+
if (Objects.isNull(members)) {
144+
return license;
145+
}
146+
if (members.size() == 1) {
147+
return members.stream().findFirst().get();
148+
}
149+
Map<AnyLicenseInfo, AnyLicenseInfo> changedMembers = new HashMap<>();
150+
for (AnyLicenseInfo member : members) {
151+
AnyLicenseInfo optimizedMember = fixSingleMemberSets(member);
152+
if (!Objects.equals(optimizedMember, member)) {
153+
changedMembers.put(member, optimizedMember);
154+
}
155+
}
156+
if (!changedMembers.isEmpty()) {
157+
Set<AnyLicenseInfo> newMembers = new HashSet<>();
158+
for (AnyLicenseInfo member : members) {
159+
newMembers.add(changedMembers.getOrDefault(member, member));
160+
}
161+
members.clear();
162+
members.addAll(newMembers);
163+
}
164+
return license;
165+
}
166+
167+
/**
168+
* Fixes any single member license sets found within an AnyLicenseInfo
169+
* @param license any type of license
170+
* @return license with any single member license sets replaced by the single member value
171+
*/
172+
private static org.spdx.library.model.v2.license.AnyLicenseInfo fixSingleMemberSetsCompatV2(org.spdx.library.model.v2.license.AnyLicenseInfo license) throws InvalidSPDXAnalysisException {
173+
if (license instanceof LicenseSet) {
174+
Collection<org.spdx.library.model.v2.license.AnyLicenseInfo> members = ((LicenseSet)license).getMembers();
175+
if (members.size() == 1) {
176+
return members.stream().findFirst().get();
177+
} else {
178+
Map<org.spdx.library.model.v2.license.AnyLicenseInfo,
179+
org.spdx.library.model.v2.license.AnyLicenseInfo> changedMembers = new HashMap<>();
180+
for (org.spdx.library.model.v2.license.AnyLicenseInfo member : members) {
181+
org.spdx.library.model.v2.license.AnyLicenseInfo optimizedMember = fixSingleMemberSetsCompatV2(member);
182+
if (!Objects.equals(optimizedMember, member)) {
183+
changedMembers.put(member, optimizedMember);
184+
}
185+
}
186+
if (!changedMembers.isEmpty()) {
187+
Set<org.spdx.library.model.v2.license.AnyLicenseInfo> newMembers = new HashSet<>();
188+
for (org.spdx.library.model.v2.license.AnyLicenseInfo member : members) {
189+
newMembers.add(changedMembers.getOrDefault(member, member));
190+
}
191+
((LicenseSet)license).setMembers(newMembers);
192+
}
193+
}
194+
}
195+
return license;
196+
}
197+
130198
/**
131199
* Parses a license string and converts it into a SPDXLicenseInfo object
132200
* Syntax - A license set must start and end with a parenthesis "("
@@ -174,8 +242,8 @@ public static AnyLicenseInfo parseSPDXLicenseString(String licenseString, @Nulla
174242
}
175243
}
176244
try {
177-
return LicenseExpressionParser.parseLicenseExpression(licenseString, store, customLicensePrefix,
178-
creationInfo, copyManager, customIdToUri);
245+
return fixSingleMemberSets(LicenseExpressionParser.parseLicenseExpression(licenseString, store, customLicensePrefix,
246+
creationInfo, copyManager, customIdToUri));
179247
} catch (LicenseParserException e) {
180248
try {
181249
InvalidLicenseExpression retval = new InvalidLicenseExpression(store, store.getNextId(IModelStore.IdType.Anonymous),

src/test/java/org/spdx/library/conversion/Spdx2to3ConverterTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1978,5 +1978,4 @@ public void testPackageSupplierNoAssertionAndNone() throws InvalidSPDXAnalysisEx
19781978
assertTrue("Result should be a Person", resultPerson instanceof Person);
19791979
assertEquals("John Doe", resultPerson.getName().get());
19801980
}
1981-
19821981
}

src/test/java/org/spdx/utility/license/LicenseExpressionParserTest.java

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ public void testSingleStdLicense() throws InvalidSPDXAnalysisException {
183183
AnyLicenseInfo result = LicenseExpressionParser.parseLicenseExpression(parseString,
184184
modelStore, DEFAULT_PREFIX, creationInfo,
185185
copyManager, idMap);
186-
assertTrue(expected.equals(result));
186+
assertEquals(expected, result);
187187
}
188188

189189

@@ -192,7 +192,7 @@ public void testSingleExtractedLicense() throws InvalidSPDXAnalysisException {
192192
AnyLicenseInfo expected = NON_STD_LICENSES[0];
193193
AnyLicenseInfo result = LicenseExpressionParser.parseLicenseExpression(parseString, modelStore,
194194
DEFAULT_PREFIX, creationInfo, copyManager, idMap);
195-
assertTrue(expected.equals(result));
195+
assertEquals(expected, result);
196196
}
197197

198198
public void testUninitializedExtractedLicense() throws InvalidSPDXAnalysisException {
@@ -209,7 +209,7 @@ public void testOrLater() throws InvalidSPDXAnalysisException {
209209
expected.setSubjectLicense(STANDARD_LICENSES[0]);
210210
AnyLicenseInfo result = LicenseExpressionParser.parseLicenseExpression(parseString,
211211
modelStore, DEFAULT_PREFIX, creationInfo, copyManager, idMap);
212-
assertTrue(expected.equals(result));
212+
assertEquals(expected, result);
213213
}
214214

215215

@@ -220,14 +220,14 @@ public void testWithException() throws InvalidSPDXAnalysisException {
220220
expected.setSubjectExtendableLicense(STANDARD_LICENSES[0]);
221221
AnyLicenseInfo result = LicenseExpressionParser.parseLicenseExpression(parseString, modelStore,
222222
DEFAULT_PREFIX, creationInfo, copyManager, idMap);
223-
assertTrue(expected.equals(result));
223+
assertEquals(expected, result);
224224
parseString = STD_IDS[0]+" WITH " + STD_EXCEPTION_IDS[0];
225225
expected = new WithAdditionOperator();
226226
expected.setSubjectAddition(STD_LICENSE_EXCEPTIONS[0]);
227227
expected.setSubjectExtendableLicense(STANDARD_LICENSES[0]);
228228
result = LicenseExpressionParser.parseLicenseExpression(parseString, modelStore,
229229
DEFAULT_PREFIX, creationInfo, copyManager, idMap);
230-
assertTrue(expected.equals(result));
230+
assertEquals(expected, result);
231231
}
232232

233233

@@ -238,7 +238,7 @@ public void testSimpleAnd() throws InvalidSPDXAnalysisException {
238238
expected.getMembers().add(NON_STD_LICENSES[0]);
239239
AnyLicenseInfo result = LicenseExpressionParser.parseLicenseExpression(parseString,
240240
modelStore, DEFAULT_PREFIX, creationInfo, copyManager, idMap);
241-
assertTrue(expected.equals(result));
241+
assertEquals(expected, result);
242242
}
243243

244244

@@ -249,7 +249,7 @@ public void testSimpleOr() throws InvalidSPDXAnalysisException {
249249
expected.getMembers().add(NON_STD_LICENSES[0]);
250250
AnyLicenseInfo result = LicenseExpressionParser.parseLicenseExpression(parseString,
251251
modelStore, DEFAULT_PREFIX, creationInfo, copyManager, idMap);
252-
assertTrue(expected.equals(result));
252+
assertEquals(expected, result);
253253
}
254254

255255

@@ -261,7 +261,7 @@ public void testLargerAnd() throws InvalidSPDXAnalysisException {
261261
NON_STD_LICENSES[1], STANDARD_LICENSES[2], STANDARD_LICENSES[3]})));
262262
AnyLicenseInfo result = LicenseExpressionParser.parseLicenseExpression(parseString, modelStore,
263263
DEFAULT_PREFIX, creationInfo, copyManager, idMap);
264-
assertTrue(expected.equals(result));
264+
assertEquals(expected, result);
265265
}
266266

267267

@@ -273,7 +273,7 @@ public void testLargerOr() throws InvalidSPDXAnalysisException {
273273
NON_STD_LICENSES[1], STANDARD_LICENSES[2], STANDARD_LICENSES[3]})));
274274
AnyLicenseInfo result = LicenseExpressionParser.parseLicenseExpression(parseString, modelStore,
275275
DEFAULT_PREFIX, creationInfo, copyManager, idMap);
276-
assertTrue(expected.equals(result));
276+
assertEquals(expected, result);
277277
}
278278

279279

@@ -285,7 +285,7 @@ public void testOuterParens() throws InvalidSPDXAnalysisException {
285285
NON_STD_LICENSES[1], STANDARD_LICENSES[2], STANDARD_LICENSES[3]})));
286286
AnyLicenseInfo result = LicenseExpressionParser.parseLicenseExpression(parseString,
287287
modelStore, DEFAULT_PREFIX, creationInfo, copyManager, idMap);
288-
assertTrue(expected.equals(result));
288+
assertEquals(expected, result);
289289
}
290290

291291

@@ -299,7 +299,7 @@ public void testInnerParens() throws InvalidSPDXAnalysisException {
299299
NON_STD_LICENSES[1], dls})));
300300
AnyLicenseInfo result = LicenseExpressionParser.parseLicenseExpression(parseString, modelStore,
301301
DEFAULT_PREFIX, creationInfo, copyManager, idMap);
302-
assertTrue(expected.equals(result));
302+
assertEquals(expected, result);
303303
}
304304

305305

@@ -314,7 +314,7 @@ public void testAndOrPrecedence() throws InvalidSPDXAnalysisException {
314314
cls, STANDARD_LICENSES[3]})));
315315
AnyLicenseInfo result = LicenseExpressionParser.parseLicenseExpression(parseString,
316316
modelStore, DEFAULT_PREFIX, creationInfo, copyManager, idMap);
317-
assertTrue(expected.equals(result));
317+
assertEquals(expected, result);
318318
}
319319

320320
public void testExternalCustomLicense() throws InvalidSPDXAnalysisException {
@@ -388,4 +388,21 @@ public void regressionMitWith() throws InvalidSPDXAnalysisException, InvalidLice
388388
AnyLicenseInfo result = LicenseInfoFactory.parseSPDXLicenseString("MIT WITH Autoconf-exception-2.0");
389389
assertEquals("MIT WITH Autoconf-exception-2.0",result.toString());
390390
}
391+
392+
public void testRegressionSameTerms() throws InvalidSPDXAnalysisException {
393+
String parseString = STD_IDS[1] + " AND " + STD_IDS[1];
394+
AnyLicenseInfo result = LicenseInfoFactory.parseSPDXLicenseString(parseString, modelStore,
395+
DEFAULT_PREFIX, creationInfo, copyManager, idMap);
396+
assertEquals(STANDARD_LICENSES[1], result);
397+
parseString = NONSTD_IDS[1] + " OR " + NONSTD_IDS[1];
398+
result = LicenseInfoFactory.parseSPDXLicenseString(parseString, modelStore,
399+
DEFAULT_PREFIX, creationInfo, copyManager, idMap);
400+
assertEquals(NON_STD_LICENSES[1], result);
401+
parseString = NONSTD_IDS[1] + " OR (" + STD_IDS[1] + " AND " + STD_IDS[1] + ")";
402+
result = LicenseInfoFactory.parseSPDXLicenseString(parseString, modelStore,
403+
DEFAULT_PREFIX, creationInfo, copyManager, idMap);
404+
assertTrue(result instanceof DisjunctiveLicenseSet);
405+
assertTrue(((DisjunctiveLicenseSet)result).getMembers().contains(NON_STD_LICENSES[1]));
406+
assertTrue(((DisjunctiveLicenseSet)result).getMembers().contains(STANDARD_LICENSES[1]));
407+
}
391408
}

0 commit comments

Comments
 (0)