diff --git a/re-contract/src/main/java/com/g2forge/reassert/contract/model/contract/license/ALicenseParser.java b/re-contract/src/main/java/com/g2forge/reassert/contract/model/contract/license/ALicenseParser.java index 22b6821d..781d8d70 100644 --- a/re-contract/src/main/java/com/g2forge/reassert/contract/model/contract/license/ALicenseParser.java +++ b/re-contract/src/main/java/com/g2forge/reassert/contract/model/contract/license/ALicenseParser.java @@ -27,6 +27,10 @@ public abstract class ALicenseParser implements IParser { public static abstract class APatternListBuilder implements IBuilder>> { protected static final IMatcher gap = pattern().charClass(false, cc -> cc.character('-').character('_').named(NamedCharacterClass.Space)).star().build(); + protected static final IMatcher parenthetical = pattern().group(g -> g.with(gap).text("(").charClass(true, cc -> cc.character(')')).plus().text(")")).opt().build(); + + protected static final IMatcher holder = pattern().group(g0 -> g0.group(g1 -> g1.with(gap).charClass(false, cc -> cc.range('a', 'z').range('A', 'Z').range('0', '9')).plus()).plus()).opt().build(); + protected static final IMatcher the = pattern().group(g -> g.text("the").with(gap)).opt().build(); protected static final IMatcher licenseReq = pattern().with(gap).text("Licen").charClass(false, cc -> cc.character('c').character('s')).text("e").group(g -> g.charClass(false, cc -> cc.character('s').character('d'))).opt().build(), licenseOpt = pattern().group(g -> g.with(licenseReq)).opt().build(); diff --git a/re-maven/src/main/java/com/g2forge/reassert/maven/MavenSystem.java b/re-maven/src/main/java/com/g2forge/reassert/maven/MavenSystem.java index 2d6b38a8..eeb1f3b6 100644 --- a/re-maven/src/main/java/com/g2forge/reassert/maven/MavenSystem.java +++ b/re-maven/src/main/java/com/g2forge/reassert/maven/MavenSystem.java @@ -12,7 +12,6 @@ import com.ctc.wstx.api.WstxInputProperties; import com.ctc.wstx.stax.WstxInputFactory; -import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.dataformat.xml.XmlFactory; import com.fasterxml.jackson.dataformat.xml.XmlMapper; diff --git a/re-standard/src/main/java/com/g2forge/reassert/standard/model/contract/license/StandardLicense.java b/re-standard/src/main/java/com/g2forge/reassert/standard/model/contract/license/StandardLicense.java index 7921e61f..a4edd7d0 100644 --- a/re-standard/src/main/java/com/g2forge/reassert/standard/model/contract/license/StandardLicense.java +++ b/re-standard/src/main/java/com/g2forge/reassert/standard/model/contract/license/StandardLicense.java @@ -31,7 +31,21 @@ public enum StandardLicense implements ILicenseFamilyEnum, ILicenseSpecific { PostgreSQL("PostgreSQL", null, null, false), Beerware("Beerware", null, null, false), FTL("FTL", null, null, false), - Perl5(null, null, null, false); + FSFAP("FSFAP", StandardLicenseFamily.Permissive, null, false), + Perl5(null, null, null, false), + LibTIFF("libtiff", StandardLicenseFamily.Permissive, null, false), + HPND(null, StandardLicenseFamily.Permissive, null, false), + Ruby(null, null, null, false), + ICU(null, null, null, false), + TCL(null, null, null, false), + LPPL(null, null, null, false), + X11(null, StandardLicenseFamily.Permissive, null, false), + W3C(null, null, null, false), + Unlicense(null, null, null, false), + Hylafax(null, null, null, false), + FSFUL(null, null, null, false), + FSFULLR(null, null, null, false), + Latex2e(null, null, null, false); static { ILicenseFamilyEnum.validate(StandardLicense.class); diff --git a/re-standard/src/main/java/com/g2forge/reassert/standard/model/contract/license/StandardLicenseParser.java b/re-standard/src/main/java/com/g2forge/reassert/standard/model/contract/license/StandardLicenseParser.java index fba4d0d0..f1f13dcf 100644 --- a/re-standard/src/main/java/com/g2forge/reassert/standard/model/contract/license/StandardLicenseParser.java +++ b/re-standard/src/main/java/com/g2forge/reassert/standard/model/contract/license/StandardLicenseParser.java @@ -34,8 +34,8 @@ public static class PatternListBuilder extends APatternListBuilder { final List> retVal = new ArrayList<>(); { // Apache - retVal.add(APatternListBuilder.pattern().with(the).text("Apache").group(g0 -> g0.group(g1 -> g1.with(gap).text("Software").group(g2 -> g2.with(gap).text("Foundation")).opt()).opt().with(licenseReq)).opt().with(FamilyVersionLicense::getVersion, versionPatternMinor).opt().with(licenseOpt).buildReq(StandardLicenseFamily.Apache::create)); - retVal.add(APatternListBuilder.pattern().with(the).text("ASF").with(licenseOpt).with(FamilyVersionLicense::getVersion, versionPatternMinor).opt().with(licenseOpt).buildReq(StandardLicenseFamily.Apache::create)); + retVal.add(APatternListBuilder.pattern().group(g -> g.text("OSI").with(gap).text("Approved").with(gap).text("::").with(gap)).opt().with(the).text("Apache").group(g0 -> g0.group(g1 -> g1.with(gap).text("Software").group(g2 -> g2.with(gap).text("Foundation")).opt()).opt().with(licenseReq)).opt().with(FamilyVersionLicense::getVersion, versionPatternMinor).opt().with(licenseOpt).with(parenthetical).buildReq(StandardLicenseFamily.Apache::create)); + retVal.add(APatternListBuilder.pattern().with(the).text("ASF").with(licenseOpt).with(FamilyVersionLicense::getVersion, versionPatternMinor).opt().with(licenseOpt).with(parenthetical).buildReq(StandardLicenseFamily.Apache::create)); retVal.add(new IMatcher() { @Override public IOptional match(String text) { @@ -47,13 +47,13 @@ public IOptional match(String text) { } { // BSD final IMatcher suffix = pattern().with(gap).group(g -> g.text(".").with(gap)).opt().group(g -> g.text("Clause").text("s").opt()).opt().build(); - retVal.add(APatternListBuilder.pattern().text("BSD").with(gap).group(BSDLicense::getClauses, g -> g.digit(10).plus().buildReq(match -> HPrimitive.parseInteger(match.getAsString()))).with(suffix).with(licenseOpt).buildReq(match -> new BSDLicense(match.getAsObject(BSDLicense::getClauses)))); - retVal.add(APatternListBuilder.pattern().group(BSDLicense::getClauses, g -> g.digit(10).plus().buildReq(match -> HPrimitive.parseInteger(match.getAsString()))).with(suffix).with(gap).text("BSD").with(licenseOpt).buildReq(match -> new BSDLicense(match.getAsObject(BSDLicense::getClauses)))); + retVal.add(APatternListBuilder.pattern().text("BSD").with(gap).group(BSDLicense::getClauses, g -> g.digit(10).plus().buildReq(match -> HPrimitive.parseInteger(match.getAsString()))).with(suffix).with(licenseOpt).with(holder).buildReq(match -> new BSDLicense(match.getAsObject(BSDLicense::getClauses)))); + retVal.add(APatternListBuilder.pattern().group(BSDLicense::getClauses, g -> g.digit(10).plus().buildReq(match -> HPrimitive.parseInteger(match.getAsString()))).with(suffix).with(gap).text("BSD").with(licenseOpt).with(holder).buildReq(match -> new BSDLicense(match.getAsObject(BSDLicense::getClauses)))); retVal.add(APatternListBuilder.pattern().group(g -> { @SuppressWarnings("unchecked") final IMatcherBuilder alt = g.alt(pattern().text("the").build(), pattern().text("revised").build(), pattern().text("new").build()); alt.with(gap); - }).opt().text("BSD").group(g -> g.with(gap).text("style")).opt().with(licenseOpt).buildReq(match -> StandardLicenseFamily.BSD)); + }).opt().text("BSD").group(g -> g.with(gap).text("style")).opt().with(licenseOpt).with(parenthetical).buildReq(match -> StandardLicenseFamily.BSD)); } { // Creative Commons final IMatcher variants; @@ -116,10 +116,15 @@ public IOptional match(String text) { } retVal.add(APatternListBuilder.pattern().with(the).group(g -> g.text("GNU")).opt().with(gap).with(pattern("Lesser Public")).with(gap).with(FamilyVersionLicense::getVersion, versionPatternMinor).opt().alt(only, APatternListBuilder.pattern().with(FamilyVersionLicense::isOrLater, orlater).build()).with(licenseOpt).buildReq(StandardLicenseFamily.LGPL::create)); } - { // MMIT - retVal.add(APatternListBuilder.pattern().with(the).text("MIT").with(licenseOpt).buildReq(match -> StandardLicense.MIT)); - retVal.add(APatternListBuilder.pattern().with(the).text("Expat").group(g -> g.text("/MIT")).opt().buildReq(match -> StandardLicense.MIT)); - retVal.add(APatternListBuilder.pattern().with(the).text("Bouncy").with(gap).text("Castle").with(licenseReq).buildReq(match -> StandardLicense.MIT)); + { // MIT + retVal.add(APatternListBuilder.pattern().with(the).text("MIT").with(licenseOpt).with(holder).buildReq(match -> StandardLicense.MIT)); + retVal.add(APatternListBuilder.pattern().with(the).text("Expat").group(g -> g.text("/MIT")).opt().with(holder).buildReq(match -> StandardLicense.MIT)); + retVal.add(APatternListBuilder.pattern().with(the).text("Bouncy").with(gap).text("Castle").with(licenseReq).with(holder).buildReq(match -> StandardLicense.MIT)); + } + { // Python + retVal.add(APatternListBuilder.pattern().text("PSF").with(FamilyVersionLicense::getVersion, versionPatternMinor).opt().with(parenthetical).buildReq(StandardLicenseFamily.PSF::create)); + retVal.add(APatternListBuilder.pattern().text("Python Software Foundation").with(licenseOpt).with(FamilyVersionLicense::getVersion, versionPatternMinor).opt().with(parenthetical).buildReq(StandardLicenseFamily.PSF::create)); + retVal.add(APatternListBuilder.pattern().text("Python").with(FamilyVersionLicense::getVersion, versionPatternMinor).opt().with(parenthetical).buildReq(StandardLicenseFamily.Python::create)); } { // Misc versioned retVal.add(APatternListBuilder.pattern().with(the).text("Artistic").group(g -> g.with(gap).alt(licenseReq, pattern().text("dist").build())).opt().with(FamilyVersionLicense::getVersion, versionPatternMinor).opt().buildReq(StandardLicenseFamily.Artistic::create)); @@ -127,8 +132,6 @@ public IOptional match(String text) { retVal.add(APatternListBuilder.pattern().with(pattern(HString.stripSuffix(StandardLicenseFamily.IndianaExtreme.getName(), "License").trim())).with(licenseOpt).with(FamilyVersionLicense::getVersion, versionPatternPatch).buildReq(StandardLicenseFamily.IndianaExtreme::create)); retVal.add(APatternListBuilder.pattern().group(g -> g.text("SIL").with(gap)).opt().text("OFL").with(FamilyVersionLicense::getVersion, versionPatternMinor).buildReq(StandardLicenseFamily.OFL::create)); retVal.add(APatternListBuilder.pattern().text("Open").with(gap).text("Font").with(licenseOpt).with(FamilyVersionLicense::getVersion, versionPatternMinor).buildReq(StandardLicenseFamily.OFL::create)); - retVal.add(APatternListBuilder.pattern().text("PSF").with(FamilyVersionLicense::getVersion, versionPatternMinor).buildReq(StandardLicenseFamily.PSF::create)); - retVal.add(APatternListBuilder.pattern().text("Python").with(FamilyVersionLicense::getVersion, versionPatternMinor).opt().buildReq(StandardLicenseFamily.Python::create)); } { // Misc versioned with patterns for (StandardLicenseFamily family : new StandardLicenseFamily[] { StandardLicenseFamily.AFL, StandardLicenseFamily.BSL, StandardLicenseFamily.EDL, StandardLicenseFamily.CDDL }) { @@ -151,6 +154,12 @@ public IOptional match(String text) { retVal.add(APatternListBuilder.pattern().with(pattern("Public Domain")).buildReq(match -> StandardLicense.PublicDomain)); retVal.add(APatternListBuilder.pattern().text("WTFPL").buildReq(match -> StandardLicense.WTFPL)); retVal.add(APatternListBuilder.pattern().text("ZLIB").with(licenseOpt).buildReq(match -> StandardLicense.ZLIB)); + retVal.add(APatternListBuilder.pattern().text("Libpng").with(licenseOpt).buildReq(match -> StandardLicense.ZLIB)); + retVal.add(APatternListBuilder.pattern().text("Unlicense").buildReq(match -> StandardLicense.Unlicense)); + + for (StandardLicense license : new StandardLicense[] { StandardLicense.FSFAP, StandardLicense.LibTIFF, StandardLicense.HPND, StandardLicense.Ruby, StandardLicense.ICU, StandardLicense.TCL, StandardLicense.LPPL, StandardLicense.X11, StandardLicense.W3C, StandardLicense.Hylafax, StandardLicense.FSFUL, StandardLicense.FSFULLR, StandardLicense.Latex2e }) { + retVal.add(APatternListBuilder.pattern().text(license.name()).with(licenseOpt).buildReq(match -> license)); + } } return Collections.unmodifiableList(retVal); } diff --git a/re-standard/src/test/java/com/g2forge/reassert/standard/model/contract/license/enum license texts.csv b/re-standard/src/test/java/com/g2forge/reassert/standard/model/contract/license/enum license texts.csv index e86d7e81..db5de315 100644 --- a/re-standard/src/test/java/com/g2forge/reassert/standard/model/contract/license/enum license texts.csv +++ b/re-standard/src/test/java/com/g2forge/reassert/standard/model/contract/license/enum license texts.csv @@ -13,6 +13,7 @@ MIT,MIT, MIT,MIT license, MIT,MIT License, MIT,The MIT License, +MIT,MIT-open-group,Allow suffix for copyright holder Owner,Owner, Perl5,Perl 5 License (GPL or Artistic), PostgreSQL,Postgres, @@ -26,7 +27,7 @@ WTFPL,WTFPL, Zlib,zlib, Zlib,Zlib, Zlib,ZLIB, -,BSD-3-clause-s,"Ensure ""clauses"" suffix must be one word" +Zlib,LibPNG,Resolve libpng license to zlib license ,Expat /MIT,The spaces around the slash make it unparseable ,foobar,Ensure a totally bogus string isn't recognized ,LPGL-2.1+,Make sure we don't parse mis-spellings since they could be other licenses @@ -36,3 +37,18 @@ Zlib,ZLIB, ,Unspecified,Literally unspecified ,Unspecified License,Literally unspecified ,XGPL,Make sure we don't recognize weird GPL variants +FSFAP,FSFAP, +LibTIFF,LibTIFF, +HPND,HPND, +Ruby,Ruby, +ICU,ICU, +TCL,TCL, +LPPL,LPPL, +X11,X11, +X11,x11, +W3C,W3C, +Unlicense,Unlicense, +Hylafax,Hylafax, +FSFUL,FSFUL, +FSFULLR,FSFULLR, +Latex2e,Latex2e, diff --git a/re-standard/src/test/java/com/g2forge/reassert/standard/model/contract/license/familyversion license texts.csv b/re-standard/src/test/java/com/g2forge/reassert/standard/model/contract/license/familyversion license texts.csv index ea2f1997..12d52039 100644 --- a/re-standard/src/test/java/com/g2forge/reassert/standard/model/contract/license/familyversion license texts.csv +++ b/re-standard/src/test/java/com/g2forge/reassert/standard/model/contract/license/familyversion license texts.csv @@ -25,6 +25,7 @@ Apache,2.0,false,"The Apache License, 2.0", Apache,2.0,false,"The Apache License, Version 2.0", Apache,,false,Apache, Apache,,false,Apache Software License, +Apache,,false,"OSI Approved :: Apache Software License", Artistic,1.0,false,Artistic 1.0, Artistic,1.0,false,Artistic-1, Artistic,1.0,false,Artistic-1.0,