diff --git a/.github/workflows/update-arlington-workflow.yml b/.github/workflows/update-arlington-workflow.yml index b9496c8d0..1a7e8e0af 100644 --- a/.github/workflows/update-arlington-workflow.yml +++ b/.github/workflows/update-arlington-workflow.yml @@ -18,6 +18,8 @@ on: - 'core/src/main/resources/org/verapdf/pdfa/validation/PDFA-4F.xml' - 'core/src/main/resources/org/verapdf/pdfa/validation/PDFUA-1.xml' - 'core/src/main/resources/org/verapdf/pdfa/validation/PDFUA-2-ISO32005.xml' + - 'core/src/main/resources/org/verapdf/pdfa/validation/WTPDF-1-0-Accessibility.xml' + - 'core/src/main/resources/org/verapdf/pdfa/validation/WTPDF-1-0-Reuse.xml' jobs: checkout-and-build: diff --git a/core/src/main/java/org/verapdf/pdfa/flavours/PDFAFlavour.java b/core/src/main/java/org/verapdf/pdfa/flavours/PDFAFlavour.java index 5936bb7da..c1170214b 100644 --- a/core/src/main/java/org/verapdf/pdfa/flavours/PDFAFlavour.java +++ b/core/src/main/java/org/verapdf/pdfa/flavours/PDFAFlavour.java @@ -98,10 +98,12 @@ public enum PDFAFlavour { PDFUA_1(Specification.ISO_14289_1, Level.NO_LEVEL), /** ua2 PDF Version 2 */ PDFUA_2(Specification.ISO_14289_2, Level.NO_LEVEL), + WTPDF_1_0_REUSE(Specification.WTPDF_1_0, Level.REUSE), + WTPDF_1_0_ACCESSIBILITY(Specification.WTPDF_1_0, Level.ACCESSIBILITY), /** wcag PDF version 2.1 */ - WCAG2_1(Specification.WCAG_2_1, Level.NO_LEVEL), + WCAG_2_1(Specification.WCAG_2_1, Level.NO_LEVEL), /** wcag PDF version 2.2 */ - WCAG2_2(Specification.WCAG_2_2, Level.NO_LEVEL); + WCAG_2_2(Specification.WCAG_2_2, Level.NO_LEVEL); private static final Map FLAVOUR_LOOKUP = new HashMap<>(); static { @@ -115,7 +117,7 @@ public enum PDFAFlavour { private final String id; private PDFAFlavour(final Specification standard, final Level level) { - this(getPrefix(standard) + standard.getPartNumber() + level.getCode(), standard, level); + this(getID(standard, level), standard, level); } private PDFAFlavour(final String id, final Specification standard, final Level level) { @@ -123,12 +125,21 @@ private PDFAFlavour(final String id, final Specification standard, final Level l this.level = level; this.id = id; } + + private static String getID(final Specification standard, final Level level) { + String levelString = level.getCode().length() > 1 ? level.getCode().substring(0, 1) : level.getCode(); + return getPrefix(standard) + standard.getPartNumber() + levelString.toLowerCase(); + } private static String getPrefix(final Specification standard) { if (SpecificationFamily.PDF_UA == standard.family) { return PDFAFlavours.PDFUA_PREFIX; - } else if (SpecificationFamily.WCAG == standard.family) { - return PDFAFlavours.WCAG2_1_PREFIX; + } + if (SpecificationFamily.WCAG == standard.family) { + return PDFAFlavours.WCAG_PREFIX; + } + if (SpecificationFamily.WTPDF == standard.family) { + return PDFAFlavours.WTPDF_PREFIX; } return ""; } @@ -167,53 +178,63 @@ public final String toString() { */ public enum Specification { /** PDF/A Version 1 */ - NO_STANDARD(IsoStandardSeries.NO_SERIES, SpecificationFamily.NONE, PDFAFlavours.NONE_ID, - PDFAFlavours.NONE, PDFAFlavours.NONE), + NO_STANDARD(IsoStandardSeries.NO_SERIES, PDFSpecification.NO_SPECIFICATION, SpecificationFamily.NONE, + PDFAFlavours.NONE_ID, PDFAFlavours.NONE_SUBPART, PDFAFlavours.NONE, PDFAFlavours.NONE), /** PDF/UA Version 1 */ - ISO_14289_1(IsoStandardSeries.ISO_14289, SpecificationFamily.PDF_UA, PDFAFlavours.ISO_14289_1_PART, - PDFAFlavours.ISO_14289_1_YEAR, + ISO_14289_1(IsoStandardSeries.ISO_14289, PDFSpecification.ISO_32000_1_7, SpecificationFamily.PDF_UA, + PDFAFlavours.ISO_14289_1_PART, PDFAFlavours.NONE_SUBPART, PDFAFlavours.ISO_14289_1_YEAR, PDFAFlavours.ISO_14289_1_DESCRIPTION), - ISO_14289_2(IsoStandardSeries.ISO_14289, SpecificationFamily.PDF_UA, PDFAFlavours.ISO_14289_2_PART, - PDFAFlavours.ISO_14289_2_YEAR, + /** PDF/UA Version 2 */ + ISO_14289_2(IsoStandardSeries.ISO_14289, PDFSpecification.ISO_32000_2_0, SpecificationFamily.PDF_UA, + PDFAFlavours.ISO_14289_2_PART, PDFAFlavours.NONE_SUBPART, PDFAFlavours.ISO_14289_2_YEAR, PDFAFlavours.ISO_14289_2_DESCRIPTION), + WTPDF_1_0(IsoStandardSeries.NO_SERIES, PDFSpecification.ISO_32000_2_0, SpecificationFamily.WTPDF, + PDFAFlavours.WTPDF_1_0_PART, PDFAFlavours.WTPDF_1_0_SUBPART, PDFAFlavours.WTPDF_1_0_YEAR, + PDFAFlavours.WTPDF_1_0_DESCRIPTION), /** PDF/A Version 1 */ - ISO_19005_1(IsoStandardSeries.ISO_19005, SpecificationFamily.PDF_A, PDFAFlavours.ISO_19005_1_PART, - PDFAFlavours.ISO_19005_1_YEAR, + ISO_19005_1(IsoStandardSeries.ISO_19005, PDFSpecification.PDF_REFERENCE_1_4, SpecificationFamily.PDF_A, + PDFAFlavours.ISO_19005_1_PART, PDFAFlavours.NONE_SUBPART, PDFAFlavours.ISO_19005_1_YEAR, PDFAFlavours.ISO_19005_1_DESCRIPTION), /** PDF/A Version 2 */ - ISO_19005_2(IsoStandardSeries.ISO_19005, SpecificationFamily.PDF_A, PDFAFlavours.ISO_19005_2_PART, - PDFAFlavours.ISO_19005_2_YEAR, + ISO_19005_2(IsoStandardSeries.ISO_19005, PDFSpecification.ISO_32000_1_7, SpecificationFamily.PDF_A, + PDFAFlavours.ISO_19005_2_PART, PDFAFlavours.NONE_SUBPART, PDFAFlavours.ISO_19005_2_YEAR, PDFAFlavours.ISO_19005_2_DESCRIPTION), /** PDF/A Version 3 */ - ISO_19005_3(IsoStandardSeries.ISO_19005, SpecificationFamily.PDF_A, PDFAFlavours.ISO_19005_3_PART, - PDFAFlavours.ISO_19005_3_YEAR, + ISO_19005_3(IsoStandardSeries.ISO_19005, PDFSpecification.ISO_32000_1_7, SpecificationFamily.PDF_A, + PDFAFlavours.ISO_19005_3_PART, PDFAFlavours.NONE_SUBPART, PDFAFlavours.ISO_19005_3_YEAR, PDFAFlavours.ISO_19005_3_DESCRIPTION), /** PDF/A Version 4 */ - ISO_19005_4(IsoStandardSeries.ISO_19005, SpecificationFamily.PDF_A, PDFAFlavours.ISO_19005_4_PART, - PDFAFlavours.ISO_19005_4_YEAR, - PDFAFlavours.ISO_19005_4_DESCRIPTION), - ISO_32005(IsoStandardSeries.ISO_32005, SpecificationFamily.TAGGED_PDF, PDFAFlavours.NONE_ID, - PDFAFlavours.ISO_32005_YEAR, + ISO_19005_4(IsoStandardSeries.ISO_19005, PDFSpecification.ISO_32000_2_0, SpecificationFamily.PDF_A, + PDFAFlavours.ISO_19005_4_PART, PDFAFlavours.NONE_SUBPART, PDFAFlavours.ISO_19005_4_YEAR, + PDFAFlavours.ISO_19005_4_DESCRIPTION), + ISO_32005(IsoStandardSeries.ISO_32005, PDFSpecification.ISO_32000_2_0, SpecificationFamily.TAGGED_PDF, + PDFAFlavours.NONE_PART, PDFAFlavours.NONE_SUBPART, PDFAFlavours.ISO_32005_YEAR, PDFAFlavours.ISO_32005_DESCRIPTION), /** WCAG Version 2.1 */ - WCAG_2_1(IsoStandardSeries.NO_SERIES, SpecificationFamily.WCAG, PDFAFlavours.WCAG_2_1_PART, - PDFAFlavours.WCAG_2_1_YEAR, PDFAFlavours.WCAG_2_1_DESCRIPTION), + WCAG_2_1(IsoStandardSeries.NO_SERIES, PDFSpecification.ISO_32000_2_0, SpecificationFamily.WCAG, + PDFAFlavours.WCAG_2_1_PART, PDFAFlavours.WCAG_2_1_SUBPART, PDFAFlavours.WCAG_2_1_YEAR, + PDFAFlavours.WCAG_2_1_DESCRIPTION), /** WCAG Version 2.2 */ - WCAG_2_2(IsoStandardSeries.NO_SERIES, SpecificationFamily.WCAG, PDFAFlavours.WCAG_2_2_PART, - PDFAFlavours.WCAG_2_2_YEAR, PDFAFlavours.WCAG_2_2_DESCRIPTION); + WCAG_2_2(IsoStandardSeries.NO_SERIES, PDFSpecification.ISO_32000_2_0, SpecificationFamily.WCAG, + PDFAFlavours.WCAG_2_2_PART, PDFAFlavours.WCAG_2_2_SUBPART, PDFAFlavours.WCAG_2_2_YEAR, + PDFAFlavours.WCAG_2_2_DESCRIPTION); private final IsoStandardSeries series; - private final int partNumber; + private final PDFSpecification pdfSpecification; + private final Integer partNumber; + private final Integer subpartNumber; private final String id; private final String year; private final SpecificationFamily family; private final String name; private final String description; - Specification(final IsoStandardSeries series, final SpecificationFamily family, final int partNumber, - final String year, final String description) { + Specification(final IsoStandardSeries series, final PDFSpecification pdfSpecification, final SpecificationFamily family, + final Integer partNumber, final Integer subpartNumber, final String year, final String description) { this.series = series; + this.pdfSpecification = pdfSpecification; this.partNumber = partNumber; + this.subpartNumber = subpartNumber; this.year = year; this.description = description; this.family = family; @@ -222,25 +243,35 @@ public enum Specification { } private String calculateID() { - if (PDFAFlavours.WCAG_2_1_DESCRIPTION.equals(description)) { - return PDFAFlavours.WCAG_2_1; + StringBuilder id = new StringBuilder(); + if (SpecificationFamily.WTPDF == this.getFamily() || SpecificationFamily.WCAG == this.getFamily()) { + id.append(this.getFamily().getFamily()); + } else { + id.append(this.getSeries().getName()); } - if (PDFAFlavours.WCAG_2_2_DESCRIPTION.equals(description)) { - return PDFAFlavours.WCAG_2_2; + if (this.getPartNumber() != null) { + id.append("-").append(this.getPartNumber()); + if (this.getSubpartNumber() != null) { + id.append(".").append(this.getSubpartNumber()); + } } - if (PDFAFlavours.ISO_32005_DESCRIPTION.equals(description)) { - return this.series.getName() + ":" + this.getYear(); + if (this.getYear() != null) { + id.append(":").append(this.getYear()); } - return this.series.getName() + "-" + this.getPartNumber() + ":" + this.getYear(); + return id.toString(); } /** * @return the part number as an int */ - public final int getPartNumber() { + public final Integer getPartNumber() { return this.partNumber; } + public final Integer getSubpartNumber() { + return this.subpartNumber; + } + /** * @return the standard part id as a String */ @@ -269,6 +300,10 @@ public final SpecificationFamily getFamily() { return this.family; } + public PDFSpecification getPdfSpecification() { + return pdfSpecification; + } + /** * @return the description */ @@ -307,7 +342,9 @@ public enum Level { /** Level F */ F(PDFAFlavours.LEVEL_F_CODE, PDFAFlavours.LEVEL_F_NAME), /** Level E */ - E(PDFAFlavours.LEVEL_E_CODE, PDFAFlavours.LEVEL_E_NAME); + E(PDFAFlavours.LEVEL_E_CODE, PDFAFlavours.LEVEL_E_NAME), + ACCESSIBILITY(PDFAFlavours.LEVEL_ACCESSIBILITY, PDFAFlavours.LEVEL_ACCESSIBILITY), + REUSE(PDFAFlavours.LEVEL_REUSE, PDFAFlavours.LEVEL_REUSE); private final String code; private final String name; @@ -388,6 +425,7 @@ public enum SpecificationFamily { NONE(PDFAFlavours.NONE), PDF_A(PDFAFlavours.PDFA), PDF_UA(PDFAFlavours.PDFUA), + WTPDF(PDFAFlavours.WTPDF), TAGGED_PDF(PDFAFlavours.TAGGED_PDF), WCAG(PDFAFlavours.WCAG); @@ -402,6 +440,13 @@ public String getFamily() { } } + public enum PDFSpecification { + NO_SPECIFICATION, + PDF_REFERENCE_1_4, + ISO_32000_1_7, + ISO_32000_2_0 + } + /** * Looks up a {@link PDFAFlavour} by two letter flavour identifier. The diff --git a/core/src/main/java/org/verapdf/pdfa/flavours/PDFAFlavours.java b/core/src/main/java/org/verapdf/pdfa/flavours/PDFAFlavours.java index d23f63b22..87075098a 100644 --- a/core/src/main/java/org/verapdf/pdfa/flavours/PDFAFlavours.java +++ b/core/src/main/java/org/verapdf/pdfa/flavours/PDFAFlavours.java @@ -35,15 +35,19 @@ final class PDFAFlavours { static final String NONE = ""; static final String PDFA = "PDF/A"; //$NON-NLS-1$ static final String PDFUA = "PDF/UA"; //$NON-NLS-1$ + static final String WTPDF = "WTPDF"; //$NON-NLS-1$ static final String TAGGED_PDF = "Tagged PDF"; //$NON-NLS-1$ static final String WCAG_2_1 = "WCAG2.1"; //$NON-NLS-1$ static final String WCAG_2_2 = "WCAG2.2"; //$NON-NLS-1$ static final String WCAG = "WCAG"; //$NON-NLS-1$ static final String PDFUA_PREFIX = "ua"; //$NON-NLS-1$ - static final String WCAG2_1_PREFIX = "wcag"; //$NON-NLS-1$ + static final String WCAG_PREFIX = "wcag"; //$NON-NLS-1$ + static final String WTPDF_PREFIX = "wt"; //$NON-NLS-1$ static final String ISO = "ISO"; //$NON-NLS-1$ static final String ISO_PREFIX = ISO + " "; //$NON-NLS-1$ static final int NONE_ID = 0; + static final Integer NONE_PART = null; + static final Integer NONE_SUBPART = null; static final int ISO_14289_ID = 14289; static final int ISO_19005_ID = 19005; static final int ISO_32000_ID = 32000; @@ -60,6 +64,7 @@ final class PDFAFlavours { static final String ISO_32005_DESCRIPTION = "Document management -- Portable document format -- PDF 1.7 and 2.0 structure namespace inclusion in ISO 32000-2"; //$NON-NLS-1$// fix static final String WCAG_2_1_DESCRIPTION = "Web Content Accessibility Guidelines 2.1"; //$NON-NLS-1$ static final String WCAG_2_2_DESCRIPTION = "Web Content Accessibility Guidelines 2.2"; //$NON-NLS-1$ + static final String WTPDF_1_0_DESCRIPTION = "Using Tagged PDF for Accessibility and Reuse in PDF 2.0"; //$NON-NLS-1$ static final int ISO_19005_1_PART = 1; static final int ISO_19005_2_PART = 2; static final int ISO_19005_3_PART = 3; @@ -67,12 +72,19 @@ final class PDFAFlavours { static final int ISO_14289_1_PART = 1; static final int ISO_14289_2_PART = 2; static final int WCAG_2_1_PART = 2; + static final int WCAG_2_1_SUBPART = 1; static final int WCAG_2_2_PART = 2; + static final int WCAG_2_2_SUBPART = 2; + static final int WTPDF_1_0_PART = 1; + static final int WTPDF_1_0_SUBPART = 0; static final String LEVEL_A_CODE = "a"; //$NON-NLS-1$ static final String LEVEL_B_CODE = "b"; //$NON-NLS-1$ static final String LEVEL_U_CODE = "u"; //$NON-NLS-1$ static final String LEVEL_E_CODE = "e"; //$NON-NLS-1$ static final String LEVEL_F_CODE = "f"; //$NON-NLS-1$ + + static final String LEVEL_REUSE = "Reuse"; //$NON-NLS-1$ + static final String LEVEL_ACCESSIBILITY = "Accessibility"; //$NON-NLS-1$ static final String LEVEL_A_NAME = "accessible"; //$NON-NLS-1$ static final String LEVEL_B_NAME = "basic"; //$NON-NLS-1$ static final String LEVEL_U_NAME = "unicode"; //$NON-NLS-1$ @@ -80,6 +92,7 @@ final class PDFAFlavours { static final String LEVEL_F_NAME = "embedded files"; //$NON-NLS-1$ static final String ISO_14289_1_YEAR = "2014"; //$NON-NLS-1$ static final String ISO_14289_2_YEAR = "2024"; //$NON-NLS-1$ + static final String WTPDF_1_0_YEAR = "2024"; //$NON-NLS-1$ static final String ISO_19005_1_YEAR = "2005"; //$NON-NLS-1$ static final String ISO_19005_2_YEAR = "2011"; //$NON-NLS-1$ static final String ISO_19005_3_YEAR = "2012"; //$NON-NLS-1$ diff --git a/core/src/main/java/org/verapdf/pdfa/flavours/PDFFlavours.java b/core/src/main/java/org/verapdf/pdfa/flavours/PDFFlavours.java new file mode 100644 index 000000000..b08bed49c --- /dev/null +++ b/core/src/main/java/org/verapdf/pdfa/flavours/PDFFlavours.java @@ -0,0 +1,44 @@ +package org.verapdf.pdfa.flavours; + +public class PDFFlavours { + + public static boolean isPDFUARelatedFlavour(PDFAFlavour flavour) { + return isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.PDF_UA) || isWTPDFFlavour(flavour) || isWCAGFlavour(flavour); + } + + public static boolean isPDFUA1RelatedFlavour(PDFAFlavour flavour) { + return isFlavour(flavour, PDFAFlavour.PDFUA_1) || isWCAGFlavour(flavour); + } + + public static boolean isPDFUA2RelatedFlavour(PDFAFlavour flavour) { + return isFlavour(flavour, PDFAFlavour.PDFUA_2) || isFlavourPart(flavour, PDFAFlavour.Specification.WTPDF_1_0); + } + + public static boolean isWCAGFlavour(PDFAFlavour flavour) { + return isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.WCAG); + } + + public static boolean isWTPDFFlavour(PDFAFlavour flavour) { + return isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.WTPDF); + } + + public static boolean isFlavour(PDFAFlavour currentFlavour, PDFAFlavour checkedFlavour) { + return currentFlavour == checkedFlavour; + } + + public static boolean isFlavourFamily(PDFAFlavour flavour, PDFAFlavour.SpecificationFamily family) { + return flavour != null && flavour.getPart().getFamily() == family; + } + + public static boolean isFlavourPart(PDFAFlavour flavour, PDFAFlavour.Specification part) { + return flavour != null && flavour.getPart() == part; + } + + public static boolean isPDFSpecification(PDFAFlavour flavour, PDFAFlavour.PDFSpecification pdfSpecification) { + return flavour != null && flavour.getPart().getPdfSpecification() == pdfSpecification; + } + + public static boolean isFlavourISOSeries(PDFAFlavour flavour, PDFAFlavour.IsoStandardSeries isoStandardSeries) { + return flavour != null && flavour.getPart().getSeries() == isoStandardSeries; + } +} diff --git a/core/src/main/java/org/verapdf/pdfa/validation/profiles/ProfileDirectoryImpl.java b/core/src/main/java/org/verapdf/pdfa/validation/profiles/ProfileDirectoryImpl.java index 771ace202..9abd4c431 100644 --- a/core/src/main/java/org/verapdf/pdfa/validation/profiles/ProfileDirectoryImpl.java +++ b/core/src/main/java/org/verapdf/pdfa/validation/profiles/ProfileDirectoryImpl.java @@ -37,6 +37,7 @@ import org.verapdf.core.Directory; import org.verapdf.core.MapBackedDirectory; import org.verapdf.pdfa.flavours.PDFAFlavour; +import org.verapdf.pdfa.flavours.PDFFlavours; /** * @author Carl Wilson @@ -158,9 +159,22 @@ private static ProfileDirectoryImpl makeVeraProfileDir() { private static String getProfilePath(PDFAFlavour flavour) { StringBuilder profilePath = new StringBuilder(); - profilePath.append(PROFILE_RESOURCE_ROOT).append(flavour.getPart().getFamily().getFamily().replace("/", "") //$NON-NLS-1$ - ).append("-").append(flavour.getPart().getPartNumber()).append(flavour.getLevel().getCode().toUpperCase()); //$NON-NLS-1$ - if (flavour == PDFAFlavour.PDFUA_2) { + profilePath.append(PROFILE_RESOURCE_ROOT); + + profilePath.append(flavour.getPart().getFamily().getFamily().replace("/", "")); //$NON-NLS-1$ + profilePath.append("-"); //$NON-NLS-1$ + profilePath.append(flavour.getPart().getPartNumber()); + if (flavour.getPart().getSubpartNumber() != null) { + profilePath.append("-"); //$NON-NLS-1$ + profilePath.append(flavour.getPart().getSubpartNumber()); + } + if (PDFFlavours.isWTPDFFlavour(flavour)) { + profilePath.append("-"); //$NON-NLS-1$ + profilePath.append(flavour.getLevel().getCode()); + } else { + profilePath.append(flavour.getLevel().getCode().toUpperCase()); //$NON-NLS-1$ + } + if (PDFFlavours.isFlavour(flavour, PDFAFlavour.PDFUA_2)) { profilePath.append("-").append("ISO32005"); } profilePath.append(XML_SUFFIX); diff --git a/veraPDFPDFAConformanceCheckerGUI.pdf b/veraPDFPDFAConformanceCheckerGUI.pdf deleted file mode 100644 index 60db7ea0f..000000000 Binary files a/veraPDFPDFAConformanceCheckerGUI.pdf and /dev/null differ