diff --git a/core/src/main/java/org/verapdf/containers/StaticCoreContainers.java b/core/src/main/java/org/verapdf/containers/StaticCoreContainers.java index cccf62d3b..567a47938 100644 --- a/core/src/main/java/org/verapdf/containers/StaticCoreContainers.java +++ b/core/src/main/java/org/verapdf/containers/StaticCoreContainers.java @@ -2,19 +2,26 @@ import org.verapdf.pdfa.flavours.PDFAFlavour; +import java.util.Collections; +import java.util.List; + public class StaticCoreContainers { - private static final ThreadLocal flavour = new ThreadLocal<>(); + private static final ThreadLocal> flavour = new ThreadLocal<>(); public static void clearAllContainers() { flavour.set(null); } - public static PDFAFlavour getFlavour() { + public static List getFlavour() { return flavour.get(); } - public static void setFlavour(PDFAFlavour flavour) { + public static void setFlavour(List flavour) { StaticCoreContainers.flavour.set(flavour); } + + public static void setFlavour(PDFAFlavour flavour) { + StaticCoreContainers.flavour.set(Collections.singletonList(flavour)); + } } diff --git a/core/src/main/java/org/verapdf/model/impl/axl/AXLExtensionSchemaProperty.java b/core/src/main/java/org/verapdf/model/impl/axl/AXLExtensionSchemaProperty.java index b5e02be62..63252343f 100644 --- a/core/src/main/java/org/verapdf/model/impl/axl/AXLExtensionSchemaProperty.java +++ b/core/src/main/java/org/verapdf/model/impl/axl/AXLExtensionSchemaProperty.java @@ -21,6 +21,7 @@ package org.verapdf.model.impl.axl; import org.verapdf.containers.StaticCoreContainers; +import org.verapdf.pdfa.flavours.PDFFlavours; import org.verapdf.xmp.XMPConst; import org.verapdf.xmp.impl.VeraPDFXMPNode; import org.verapdf.model.tools.xmp.ValidatorsContainer; @@ -99,7 +100,7 @@ public Boolean getisValueTypeValidText() { @Override public Boolean getisValueTypeDefined() { - if (StaticCoreContainers.getFlavour() != null && StaticCoreContainers.getFlavour().getPart() == PDFAFlavour.Specification.ISO_19005_1) { + if (PDFFlavours.isFlavourPart(StaticCoreContainers.getFlavour(), PDFAFlavour.Specification.ISO_19005_1)) { return isValueTypeValidForPDFA_1(); } return isValueTypeValidForPDFA_2_3(); diff --git a/core/src/main/java/org/verapdf/pdfa/AbstractFoundry.java b/core/src/main/java/org/verapdf/pdfa/AbstractFoundry.java index 7d5ab43aa..538d5b105 100644 --- a/core/src/main/java/org/verapdf/pdfa/AbstractFoundry.java +++ b/core/src/main/java/org/verapdf/pdfa/AbstractFoundry.java @@ -28,6 +28,7 @@ import org.verapdf.pdfa.validation.validators.ValidatorConfig; import org.verapdf.pdfa.validation.validators.ValidatorFactory; +import java.util.List; /** * @author Carl Wilson * carlwilson AT github @@ -57,6 +58,16 @@ public PDFAValidator createValidator(ValidatorConfig config, PDFAFlavour flavour config.isRecordPasses(), config.showErrorMessages(), config.getShowProgress()); } + @Override + public PDFAValidator createValidator(ValidatorConfig config, List flavours) { + if (config.getMaxFails() > 0) { + return createFailFastValidator(flavours, config.getMaxFails(), config.getMaxNumberOfDisplayedFailedChecks(), + config.isRecordPasses(), config.showErrorMessages(), config.getShowProgress()); + } + return createValidator(flavours, config.getMaxNumberOfDisplayedFailedChecks(), + config.isRecordPasses(), config.showErrorMessages(), config.getShowProgress()); + } + @Override public PDFAValidator createValidator(ValidatorConfig config, ValidationProfile profile) { if (config.getMaxFails() > 0) { @@ -67,6 +78,11 @@ public PDFAValidator createValidator(ValidatorConfig config, ValidationProfile p config.isRecordPasses(), config.showErrorMessages(), config.getShowProgress()); } + @Override + public PDFAValidator createValidator(List flavours) { + return ValidatorFactory.createValidator(flavours); + } + @Override public PDFAValidator createValidator(PDFAFlavour flavour, boolean logSuccess) { return ValidatorFactory.createValidator(flavour, logSuccess); @@ -84,6 +100,13 @@ public PDFAValidator createValidator(PDFAFlavour flavour, int maxNumberOfDisplay showProgress); } + @Override + public PDFAValidator createValidator(List flavours, int maxNumberOfDisplayedFailedChecks, + boolean logSuccess, boolean showErrorMessages, boolean showProgress) { + return ValidatorFactory.createValidatorByFlavours(flavours, maxNumberOfDisplayedFailedChecks, logSuccess, showErrorMessages, + showProgress); + } + @Override public PDFAValidator createValidator(ValidationProfile profile, int maxNumberOfDisplayedFailedChecks, boolean logSuccess, boolean showErrorMessages, boolean showProgress) { @@ -98,6 +121,13 @@ public PDFAValidator createFailFastValidator(PDFAFlavour flavour, int maxFailure showErrorMessages, showProgress); } + @Override + public PDFAValidator createFailFastValidator(List flavours, int maxFailures, int maxNumberOfDisplayedFailedChecks, + boolean logSuccess, boolean showErrorMessages, boolean showProgress) { + return ValidatorFactory.createValidator(flavours, logSuccess, maxFailures, maxNumberOfDisplayedFailedChecks, + showErrorMessages, showProgress); + } + @Override public PDFAValidator createFailFastValidator(ValidationProfile profile, int maxFailures, int maxNumberOfDisplayedFailedChecks, boolean logSuccess, boolean showErrorMessages, boolean showProgress) { diff --git a/core/src/main/java/org/verapdf/pdfa/PDFAParser.java b/core/src/main/java/org/verapdf/pdfa/PDFAParser.java index c6b92a726..607e2e83c 100644 --- a/core/src/main/java/org/verapdf/pdfa/PDFAParser.java +++ b/core/src/main/java/org/verapdf/pdfa/PDFAParser.java @@ -55,6 +55,10 @@ public interface PDFAParser extends Component { */ public PDFAFlavour getFlavour(); + public List getFlavours(); + + public void setFlavours(List flavours); + /** * @return the {@link org.verapdf.metadata.fixer.entity.PDFDocument} parsed. */ diff --git a/core/src/main/java/org/verapdf/pdfa/PDFAValidator.java b/core/src/main/java/org/verapdf/pdfa/PDFAValidator.java index c54007b4a..f6fd272f0 100644 --- a/core/src/main/java/org/verapdf/pdfa/PDFAValidator.java +++ b/core/src/main/java/org/verapdf/pdfa/PDFAValidator.java @@ -26,6 +26,8 @@ import org.verapdf.pdfa.validation.profiles.ValidationProfile; import org.verapdf.processor.reports.enums.JobEndStatus; +import java.util.List; + /** * A PDFAValidator performs a series of checks on PDF/A documents to verify that * the document conforms to a specific PDF/A flavour. @@ -65,6 +67,8 @@ public interface PDFAValidator extends Component { */ public ValidationResult validate(PDFAParser toValidate) throws ValidationException; + public List validateAll(PDFAParser toValidate) throws ValidationException; + public String getValidationProgressString(); public void cancelValidation(JobEndStatus endStatus); diff --git a/core/src/main/java/org/verapdf/pdfa/VeraPDFFoundry.java b/core/src/main/java/org/verapdf/pdfa/VeraPDFFoundry.java index 6fda91af0..f213eeb67 100644 --- a/core/src/main/java/org/verapdf/pdfa/VeraPDFFoundry.java +++ b/core/src/main/java/org/verapdf/pdfa/VeraPDFFoundry.java @@ -32,6 +32,7 @@ import java.io.File; import java.io.InputStream; +import java.util.List; /** * The veraPDFFoundry interface provides methods for creating implementations of @@ -167,6 +168,20 @@ public PDFAParser createParser(File pdfFile) */ public PDFAValidator createValidator(ValidatorConfig config, PDFAFlavour flavour); + /** + * Obtain a new {@link PDFAValidator} instance that uses the list of a custom + * {@link org.verapdf.pdfa.flavours.PDFAFlavour}s. + * + * @param config + * a {@link ValidatorConfig} instance used to configure the + * {@link PDFAValidator} + * @param flavours + * the list of particular {@link org.verapdf.pdfa.flavours.PDFAFlavour}s + * to validated against. + * @return an appropriately configured {@link PDFAValidator} instance. + */ + public PDFAValidator createValidator(ValidatorConfig config, List flavours); + /** * Creates a new {@link PDFAValidator} instance that uses one of the * {@link ValidationProfile}s packaged as a core library resource. While @@ -188,6 +203,23 @@ public PDFAParser createParser(File pdfFile) */ public PDFAValidator createValidator(PDFAFlavour flavour, boolean logSuccess); + /** + * Creates a new {@link PDFAValidator} instance that uses + * {@link ValidationProfile}s packaged as a core library resource. While + * these profiles are not guaranteed to be up to date, they are available + * when offline. A {@link org.verapdf.pdfa.validation.profiles.ProfileDirectory} populated with the pre-loaded + * profiles can be obtained by calling + * {@link org.verapdf.pdfa.validation.profiles.Profiles#getVeraProfileDirectory()}. + * + * @param flavours + * list of the {@link PDFAFlavour} that are associated with the + * {@code ValidationProfile} to used to initialise the + * {@code PDFAValidator}. + * @return a {@link PDFAValidator} instance initialised from the passed + * parameters + */ + public PDFAValidator createValidator(List flavours); + /** * Creates a new {@link PDFAValidator} initialised with the passed profile * and chosen passed test logging. @@ -207,6 +239,9 @@ public PDFAParser createParser(File pdfFile) public PDFAValidator createValidator(PDFAFlavour flavour, int maxNumberOfDisplayedFailedChecks, boolean logSuccess, boolean showErrorMessages, boolean showProgress); + public PDFAValidator createValidator(List flavour, int maxNumberOfDisplayedFailedChecks, + boolean logSuccess, boolean showErrorMessages, boolean showProgress); + public PDFAValidator createValidator(ValidationProfile profile, int maxNumberOfDisplayedFailedChecks, boolean logSuccess, boolean showErrorMessages, boolean showProgress); @@ -230,6 +265,9 @@ public PDFAValidator createValidator(ValidationProfile profile, int maxNumberOfD public PDFAValidator createFailFastValidator(PDFAFlavour flavour, int maxFailures, int maxNumberOfDisplayedFailedChecks, boolean logSuccess, boolean showErrorMessages, boolean showProgress); + public PDFAValidator createFailFastValidator(List flavours, int maxFailures, int maxNumberOfDisplayedFailedChecks, + boolean logSuccess, boolean showErrorMessages, boolean showProgress); + /** * Creates a new {@link PDFAValidator} initialised with the passed profile, * requested fast failing behaviour and configured NOT to log passed checks. diff --git a/core/src/main/java/org/verapdf/pdfa/flavours/PDFFlavours.java b/core/src/main/java/org/verapdf/pdfa/flavours/PDFFlavours.java index b08bed49c..73c7bb816 100644 --- a/core/src/main/java/org/verapdf/pdfa/flavours/PDFFlavours.java +++ b/core/src/main/java/org/verapdf/pdfa/flavours/PDFFlavours.java @@ -1,6 +1,17 @@ package org.verapdf.pdfa.flavours; +import java.util.List; + public class PDFFlavours { + + public static boolean isPDFUARelatedFlavour(List flavours) { + for (PDFAFlavour flavour : flavours) { + if (isPDFUARelatedFlavour(flavour)) { + return true; + } + } + return false; + } public static boolean isPDFUARelatedFlavour(PDFAFlavour flavour) { return isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.PDF_UA) || isWTPDFFlavour(flavour) || isWCAGFlavour(flavour); @@ -10,17 +21,54 @@ public static boolean isPDFUA1RelatedFlavour(PDFAFlavour flavour) { return isFlavour(flavour, PDFAFlavour.PDFUA_1) || isWCAGFlavour(flavour); } + public static boolean isPDFUA2RelatedFlavour(List flavours) { + for (PDFAFlavour flavour : flavours) { + if (isPDFUA2RelatedFlavour(flavour)) { + return true; + } + } + return false; + } + public static boolean isPDFUA2RelatedFlavour(PDFAFlavour flavour) { return isFlavour(flavour, PDFAFlavour.PDFUA_2) || isFlavourPart(flavour, PDFAFlavour.Specification.WTPDF_1_0); } + public static boolean isWCAGFlavour(List flavours) { + for (PDFAFlavour flavour : flavours) { + if (isWCAGFlavour(flavour)) { + return true; + } + } + return false; + } + + public static boolean isWCAGFlavour(PDFAFlavour flavour) { return isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.WCAG); } - + + public static boolean isWTPDFFlavour(List flavours) { + for (PDFAFlavour flavour : flavours) { + if (isWTPDFFlavour(flavour)) { + return true; + } + } + return false; + } + public static boolean isWTPDFFlavour(PDFAFlavour flavour) { return isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.WTPDF); } + + public static boolean isFlavour(List flavours, PDFAFlavour checkedFlavour) { + for (PDFAFlavour flavour : flavours) { + if (isFlavour(flavour, checkedFlavour)) { + return true; + } + } + return false; + } public static boolean isFlavour(PDFAFlavour currentFlavour, PDFAFlavour checkedFlavour) { return currentFlavour == checkedFlavour; @@ -29,11 +77,29 @@ public static boolean isFlavour(PDFAFlavour currentFlavour, PDFAFlavour checkedF public static boolean isFlavourFamily(PDFAFlavour flavour, PDFAFlavour.SpecificationFamily family) { return flavour != null && flavour.getPart().getFamily() == family; } + + public static boolean isFlavourPart(List flavours, PDFAFlavour.Specification part) { + for (PDFAFlavour flavour : flavours) { + if (isFlavourPart(flavour, part)) { + return true; + } + } + return false; + } public static boolean isFlavourPart(PDFAFlavour flavour, PDFAFlavour.Specification part) { return flavour != null && flavour.getPart() == part; } + public static boolean isPDFSpecification(List flavours, PDFAFlavour.PDFSpecification pdfSpecification) { + for (PDFAFlavour flavour : flavours) { + if (isPDFSpecification(flavour, pdfSpecification)) { + return true; + } + } + return false; + } + public static boolean isPDFSpecification(PDFAFlavour flavour, PDFAFlavour.PDFSpecification pdfSpecification) { return flavour != null && flavour.getPart().getPdfSpecification() == pdfSpecification; } diff --git a/core/src/main/java/org/verapdf/pdfa/validation/profiles/ProfileDirectory.java b/core/src/main/java/org/verapdf/pdfa/validation/profiles/ProfileDirectory.java index 07eb07862..6fc18f068 100644 --- a/core/src/main/java/org/verapdf/pdfa/validation/profiles/ProfileDirectory.java +++ b/core/src/main/java/org/verapdf/pdfa/validation/profiles/ProfileDirectory.java @@ -20,6 +20,7 @@ */ package org.verapdf.pdfa.validation.profiles; +import java.util.List; import java.util.NoSuchElementException; import java.util.Set; @@ -72,6 +73,8 @@ public interface ProfileDirectory { * if flavour is null */ public ValidationProfile getValidationProfileByFlavour(PDFAFlavour flavour); + + public List getValidationProfilesByFlavours(List flavours); /** * @return the full set of {@link ValidationProfile}s held in the directory. 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 6cd4cd7a3..6a5fa07a7 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 @@ -31,7 +31,8 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; - +import java.util.List; +import java.util.LinkedList; import javax.xml.bind.JAXBException; import org.verapdf.core.Directory; @@ -107,6 +108,15 @@ public ValidationProfile getValidationProfileByFlavour(PDFAFlavour flavour) { return profile; } + @Override + public List getValidationProfilesByFlavours(List flavours) { + List profiles = new LinkedList<>(); + for (PDFAFlavour flavour : flavours) { + profiles.add(getValidationProfileByFlavour(flavour)); + } + return profiles; + } + /** * { @inheritDoc } */ diff --git a/core/src/main/java/org/verapdf/pdfa/validation/validators/BaseValidator.java b/core/src/main/java/org/verapdf/pdfa/validation/validators/BaseValidator.java index b7c5d6718..515654736 100644 --- a/core/src/main/java/org/verapdf/pdfa/validation/validators/BaseValidator.java +++ b/core/src/main/java/org/verapdf/pdfa/validation/validators/BaseValidator.java @@ -33,6 +33,7 @@ import org.verapdf.model.baselayer.Object; import org.verapdf.pdfa.PDFAParser; import org.verapdf.pdfa.PDFAValidator; +import org.verapdf.pdfa.flavours.PDFAFlavour; import org.verapdf.pdfa.results.Location; import org.verapdf.pdfa.results.TestAssertion; import org.verapdf.pdfa.results.TestAssertion.Status; @@ -43,29 +44,27 @@ import java.net.URI; import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @author Carl Wilson */ public class BaseValidator implements PDFAValidator { + private static final Logger LOGGER = Logger.getLogger(BaseValidator.class.getCanonicalName()); public static final int DEFAULT_MAX_NUMBER_OF_DISPLAYED_FAILED_CHECKS = 100; private static final int MAX_CHECKS_NUMBER = 10_000; private static final URI componentId = URI.create("http://pdfa.verapdf.org/validators#default"); private static final String componentName = "veraPDF Validator"; private static final ComponentDetails componentDetails = Components.libraryDetails(componentId, componentName); - private final ValidationProfile profile; + List validators = new LinkedList<>(); private ScriptableObject scope; private final Deque objectsStack = new ArrayDeque<>(); private final Deque objectsContext = new ArrayDeque<>(); - private final Map> deferredRules = new HashMap<>(); - protected final List results = new ArrayList<>(); - private final HashMap failedChecks = new HashMap<>(); - protected int testCounter = 0; protected volatile boolean abortProcessing = false; protected final boolean logPassedChecks; protected final int maxNumberOfDisplayedFailedChecks; - protected boolean isCompliant = true; private boolean showErrorMessages = false; protected final ValidationProgress validationProgress; protected volatile JobEndStatus jobEndStatus = JobEndStatus.NORMAL; @@ -78,32 +77,68 @@ protected BaseValidator(final ValidationProfile profile) { this(profile, false); } + protected BaseValidator(final List profiles) { + this(profiles, DEFAULT_MAX_NUMBER_OF_DISPLAYED_FAILED_CHECKS, false, false, false); + } + protected BaseValidator(final ValidationProfile profile, final boolean logPassedChecks) { this(profile, DEFAULT_MAX_NUMBER_OF_DISPLAYED_FAILED_CHECKS, logPassedChecks, false, false); } protected BaseValidator(final ValidationProfile profile, final int maxNumberOfDisplayedFailedChecks, final boolean logPassedChecks, final boolean showErrorMessages, boolean showProgress) { + this(Collections.singletonList(profile), maxNumberOfDisplayedFailedChecks, logPassedChecks, showErrorMessages, showProgress); + } + + protected BaseValidator(final List profiles, final int maxNumberOfDisplayedFailedChecks, + final boolean logPassedChecks, final boolean showErrorMessages, boolean showProgress) { super(); - this.profile = profile; + createCompatibleValidators(profiles); this.maxNumberOfDisplayedFailedChecks = maxNumberOfDisplayedFailedChecks; this.logPassedChecks = logPassedChecks; this.showErrorMessages = showErrorMessages; this.validationProgress = new ValidationProgress(showProgress); } - /* - * (non-Javadoc) - * - * @see org.verapdf.pdfa.PDFAValidator#getProfile() - */ + private void createCompatibleValidators(List profiles) { + PDFAFlavour flavour = profiles.get(0).getPDFAFlavour(); + PDFAFlavour.PDFSpecification pdfSpecification = flavour.getPart().getPdfSpecification(); + for (ValidationProfile profile : profiles) { + PDFAFlavour currentFlavour = profile.getPDFAFlavour(); + PDFAFlavour.PDFSpecification currentPDFSpecification = currentFlavour.getPart().getPdfSpecification(); + if (pdfSpecification == currentPDFSpecification) { + validators.add(new FlavourValidator(profile)); + } else { + LOGGER.log(Level.WARNING,String.format("PDF version %s of detected flavour %s is incompatible with the PDF version %s of other detected flavour %s. The validation of flavour %s is skipped", + currentPDFSpecification, currentFlavour, pdfSpecification, flavour, currentFlavour)); + } + } + } + + @Override public ValidationProfile getProfile() { - return this.profile; + return this.validators.get(0).getProfile(); + } + + private List getFlavours() { + List flavours = new LinkedList<>(); + for (FlavourValidator validator : validators) { + flavours.add(validator.getProfile().getPDFAFlavour()); + } + return flavours; } @Override public ValidationResult validate(PDFAParser toValidate) throws ValidationException { + validators = Collections.singletonList(validators.get(0)); + List validationResults = validateAll(toValidate); + return validationResults.get(0); + } + + @Override + public List validateAll(PDFAParser toValidate) throws ValidationException { + toValidate.setFlavours(getFlavours()); try { return this.validate(toValidate.getRoot()); } catch (RuntimeException e) { @@ -129,7 +164,7 @@ public void cancelValidation(JobEndStatus endStatus) { this.abortProcessing = true; } - protected ValidationResult validate(Object root) throws ValidationException { + protected List validate(Object root) throws ValidationException { initialise(); this.validationProgress.updateVariables(); this.rootType = root.getObjectType(); @@ -146,45 +181,48 @@ protected ValidationResult validate(Object root) throws ValidationException { this.validationProgress.updateNumberOfObjectsToBeProcessed(objectsStack.size()); } - for (Map.Entry> entry : this.deferredRules.entrySet()) { - for (ObjectWithContext objectWithContext : entry.getValue()) { - checkObjWithRule(objectWithContext.getObject(), objectWithContext.getContext(), entry.getKey()); - } + for (FlavourValidator validator : validators) { + for (Map.Entry> entry : validator.getDeferredRules().entrySet()) { + for (ObjectWithContext objectWithContext : entry.getValue()) { + checkObjWithRule(validator, objectWithContext.getObject(), objectWithContext.getContext(), entry.getKey()); + } + } } this.validationProgress.showProgressAfterValidation(); JavaScriptEvaluator.exitContext(); - return ValidationResults.resultFromValues(this.profile, this.results, this.failedChecks, this.isCompliant, - this.testCounter, this.jobEndStatus); + List results = new LinkedList<>(); + for (FlavourValidator validator : validators) { + results.add(ValidationResults.resultFromValues(validator.getProfile(), validator.results, validator.getFailedChecks(), validator.isCompliant, + validator.testCounter, this.jobEndStatus)); + } + return results; } protected void initialise() { this.scope = JavaScriptEvaluator.initialise(); - this.failedChecks.clear(); this.objectsStack.clear(); this.objectsContext.clear(); - this.deferredRules.clear(); - this.results.clear(); this.idSet.clear(); - this.testCounter = 0; - this.isCompliant = true; initializeAllVariables(); } private void initializeAllVariables() { - for (Variable var : this.profile.getVariables()) { - if (var == null) { - continue; - } + for (FlavourValidator flavourValidator : validators) { + for (Variable var : flavourValidator.getProfile().getVariables()) { + if (var == null) { + continue; + } - java.lang.Object res = JavaScriptEvaluator.evaluateString(var.getDefaultValue(), this.scope); + java.lang.Object res = JavaScriptEvaluator.evaluateString(var.getDefaultValue(), this.scope); - if (res instanceof NativeJavaObject) { - res = ((NativeJavaObject) res).unwrap(); - } - this.scope.put(var.getName(), this.scope, res); + if (res instanceof NativeJavaObject) { + res = ((NativeJavaObject) res).unwrap(); + } + this.scope.put(var.getName(), this.scope, res); + } } } @@ -210,13 +248,15 @@ private void updateVariables(Object object) { } private void updateVariableForObjectWithType(Object object, String objectType) { - for (Variable var : this.profile.getVariablesByObject(objectType)) { - if (var == null) { - continue; - } - java.lang.Object variable = JavaScriptEvaluator.evalVariableResult(var, object, this.scope); + for (FlavourValidator flavourValidator : validators) { + for (Variable var : flavourValidator.getProfile().getVariablesByObject(objectType)) { + if (var == null) { + continue; + } + java.lang.Object variable = JavaScriptEvaluator.evalVariableResult(var, object, this.scope); - this.scope.put(var.getName(), this.scope, variable); + this.scope.put(var.getName(), this.scope, variable); + } } } @@ -277,17 +317,18 @@ private boolean checkRequired(Object obj) { private boolean checkAllRules(Object checkObject, String checkContext) { boolean res = true; - Set roolsForObject = this.profile.getRulesByObject(checkObject.getObjectType()); - for (Rule rule : roolsForObject) { - res &= firstProcessObjectWithRule(checkObject, checkContext, rule); - } - - for (String checkType : checkObject.getSuperTypes()) { - roolsForObject = this.profile.getRulesByObject(checkType); - if (roolsForObject != null) { - for (Rule rule : roolsForObject) { - if (rule != null) { - res &= firstProcessObjectWithRule(checkObject, checkContext, rule); + for (FlavourValidator flavourValidator : validators) { + Set roolsForObject = flavourValidator.getProfile().getRulesByObject(checkObject.getObjectType()); + for (Rule rule : roolsForObject) { + res &= firstProcessObjectWithRule(flavourValidator, checkObject, checkContext, rule); + } + for (String checkType : checkObject.getSuperTypes()) { + roolsForObject = flavourValidator.getProfile().getRulesByObject(checkType); + if (roolsForObject != null) { + for (Rule rule : roolsForObject) { + if (rule != null) { + res &= firstProcessObjectWithRule(flavourValidator, checkObject, checkContext, rule); + } } } } @@ -295,53 +336,53 @@ private boolean checkAllRules(Object checkObject, String checkContext) { return res; } - private boolean firstProcessObjectWithRule(Object checkObject, String checkContext, Rule rule) { + public boolean firstProcessObjectWithRule(FlavourValidator flavourValidator, Object checkObject, String checkContext, Rule rule) { Boolean deferred = rule.getDeferred(); if (deferred != null && deferred) { - List list = this.deferredRules.computeIfAbsent(rule, k -> new ArrayList<>()); - list.add(new ObjectWithContext(checkObject, checkContext)); + List list = flavourValidator.getDeferredRules().computeIfAbsent(rule, k -> new ArrayList<>()); + list.add(new BaseValidator.ObjectWithContext(checkObject, checkContext)); return true; } - return checkObjWithRule(checkObject, checkContext, rule); + return checkObjWithRule(flavourValidator, checkObject, checkContext, rule); } - private boolean checkObjWithRule(Object obj, String contextForRule, Rule rule) { + private boolean checkObjWithRule(FlavourValidator flavourValidator, Object obj, String contextForRule, Rule rule) { boolean testEvalResult = JavaScriptEvaluator.getTestEvalResult(obj, rule, this.scope); - this.processAssertionResult(testEvalResult, contextForRule, rule, obj); + this.processAssertionResult(flavourValidator, testEvalResult, contextForRule, rule, obj); - this.validationProgress.updateNumberOfFailedChecks(this.failedChecks.size()); + this.validationProgress.updateNumberOfFailedChecks(flavourValidator.getFailedChecks().size()); this.validationProgress.incrementNumberOfChecks(); return testEvalResult; } - protected void processAssertionResult(final boolean assertionResult, final String locationContext, + protected void processAssertionResult(FlavourValidator flavourValidator, final boolean assertionResult, final String locationContext, final Rule rule, final Object obj) { if (!this.abortProcessing) { - this.testCounter++; - if (this.isCompliant) { - this.isCompliant = assertionResult; + flavourValidator.testCounter++; + if (flavourValidator.isCompliant) { + flavourValidator.isCompliant = assertionResult; } if (!assertionResult) { - int failedChecksNumberOfRule = failedChecks.getOrDefault(rule.getRuleId(), 0); - failedChecks.put(rule.getRuleId(), ++failedChecksNumberOfRule); + int failedChecksNumberOfRule = flavourValidator.getFailedChecks().getOrDefault(rule.getRuleId(), 0); + flavourValidator.getFailedChecks().put(rule.getRuleId(), ++failedChecksNumberOfRule); if ((failedChecksNumberOfRule <= maxNumberOfDisplayedFailedChecks || maxNumberOfDisplayedFailedChecks == -1) && - (this.results.size() <= MAX_CHECKS_NUMBER || failedChecksNumberOfRule <= 1)) { + (flavourValidator.results.size() <= MAX_CHECKS_NUMBER || failedChecksNumberOfRule <= 1)) { Location location = ValidationResults.locationFromValues(this.rootType, locationContext); List errorArguments = showErrorMessages ? JavaScriptEvaluator.getErrorArgumentsResult(obj, rule.getError().getArguments(), this.scope) : Collections.emptyList(); String errorMessage = showErrorMessages ? createErrorMessage(rule.getError().getMessage(), errorArguments) : null; - TestAssertion assertion = ValidationResults.assertionFromValues(this.testCounter, rule.getRuleId(), + TestAssertion assertion = ValidationResults.assertionFromValues(flavourValidator.testCounter, rule.getRuleId(), Status.FAILED, rule.getDescription(), location, obj.getContext(), errorMessage, errorArguments); - this.results.add(assertion); + flavourValidator.results.add(assertion); } - } else if (this.logPassedChecks && this.results.size() <= MAX_CHECKS_NUMBER) { + } else if (this.logPassedChecks && flavourValidator.results.size() <= MAX_CHECKS_NUMBER) { Location location = ValidationResults.locationFromValues(this.rootType, locationContext); - TestAssertion assertion = ValidationResults.assertionFromValues(this.testCounter, rule.getRuleId(), + TestAssertion assertion = ValidationResults.assertionFromValues(flavourValidator.testCounter, rule.getRuleId(), Status.PASSED, rule.getDescription(), location, obj.getContext(), null, Collections.emptyList()); - this.results.add(assertion); + flavourValidator.results.add(assertion); } } } @@ -364,7 +405,7 @@ public void close() { */ } - private static class ObjectWithContext { + public static class ObjectWithContext { private final Object object; private final String context; diff --git a/core/src/main/java/org/verapdf/pdfa/validation/validators/FastFailValidator.java b/core/src/main/java/org/verapdf/pdfa/validation/validators/FastFailValidator.java index 869ce0783..38089a7bd 100644 --- a/core/src/main/java/org/verapdf/pdfa/validation/validators/FastFailValidator.java +++ b/core/src/main/java/org/verapdf/pdfa/validation/validators/FastFailValidator.java @@ -27,6 +27,9 @@ import org.verapdf.pdfa.validation.profiles.ValidationProfile; import org.verapdf.model.baselayer.Object; +import java.util.Collections; +import java.util.List; + /** * @author Carl Wilson * @@ -50,14 +53,20 @@ protected FastFailValidator(final ValidationProfile profile, final boolean logPa protected FastFailValidator(final ValidationProfile profile, final boolean logPassedChecks, final int maxFailedTests, final boolean showErrorMessages, boolean showProgress, int maxNumberOfDisplayedFailedChecks) { - super(profile, maxNumberOfDisplayedFailedChecks, logPassedChecks, showErrorMessages, showProgress); + this(Collections.singletonList(profile), logPassedChecks, maxFailedTests, showErrorMessages, showProgress, maxNumberOfDisplayedFailedChecks); + } + + protected FastFailValidator(final List profiles, final boolean logPassedChecks, + final int maxFailedTests, final boolean showErrorMessages, boolean showProgress, + int maxNumberOfDisplayedFailedChecks) { + super(profiles, maxNumberOfDisplayedFailedChecks, logPassedChecks, showErrorMessages, showProgress); this.maxFailedTests = maxFailedTests; } @Override - protected void processAssertionResult(final boolean assertionResult, + protected void processAssertionResult(FlavourValidator flavourValidator, final boolean assertionResult, final String locationContext, final Rule rule, final Object obj) { - super.processAssertionResult(assertionResult, locationContext, rule, obj); + super.processAssertionResult(flavourValidator, assertionResult, locationContext, rule, obj); if (!assertionResult) { this.failureCount++; if ((this.maxFailedTests > 0) && (this.failureCount >= this.maxFailedTests)) { diff --git a/core/src/main/java/org/verapdf/pdfa/validation/validators/FlavourValidator.java b/core/src/main/java/org/verapdf/pdfa/validation/validators/FlavourValidator.java new file mode 100644 index 000000000..c736c9101 --- /dev/null +++ b/core/src/main/java/org/verapdf/pdfa/validation/validators/FlavourValidator.java @@ -0,0 +1,38 @@ +package org.verapdf.pdfa.validation.validators; + +import org.verapdf.pdfa.results.TestAssertion; +import org.verapdf.pdfa.validation.profiles.Rule; +import org.verapdf.pdfa.validation.profiles.RuleId; +import org.verapdf.pdfa.validation.profiles.ValidationProfile; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FlavourValidator { + + private final ValidationProfile profile; + + protected boolean isCompliant = true; + private final Map> deferredRules = new HashMap<>(); + protected final List results = new ArrayList<>(); + private final HashMap failedChecks = new HashMap<>(); + protected int testCounter = 0; + + public FlavourValidator(ValidationProfile profile) { + this.profile = profile; + } + + public ValidationProfile getProfile() { + return this.profile; + } + + public Map> getDeferredRules() { + return deferredRules; + } + + public HashMap getFailedChecks() { + return failedChecks; + } +} diff --git a/core/src/main/java/org/verapdf/pdfa/validation/validators/ValidatorFactory.java b/core/src/main/java/org/verapdf/pdfa/validation/validators/ValidatorFactory.java index c515b91a2..c6ae9c109 100644 --- a/core/src/main/java/org/verapdf/pdfa/validation/validators/ValidatorFactory.java +++ b/core/src/main/java/org/verapdf/pdfa/validation/validators/ValidatorFactory.java @@ -25,6 +25,7 @@ import java.io.InputStream; import java.io.OutputStream; +import java.util.List; import java.util.logging.Level; import javax.xml.bind.JAXBException; @@ -72,6 +73,13 @@ public static PDFAValidator createValidator(final PDFAFlavour flavour, final boo logPassedChecks); } + public static PDFAValidator createValidator(final List flavours) { + if (flavours == null) { + throw new IllegalArgumentException("Parameter (List flavours) cannot be null."); + } + return new BaseValidator(Profiles.getVeraProfileDirectory().getValidationProfilesByFlavours(flavours)); + } + public static PDFAValidator createValidator(final PDFAFlavour flavour, final int maxNumberOfDisplayedFailedChecks, final boolean logPassedChecks, final boolean showErrorMessages, boolean showProgress) { @@ -82,6 +90,16 @@ public static PDFAValidator createValidator(final PDFAFlavour flavour, final int maxNumberOfDisplayedFailedChecks, logPassedChecks, showErrorMessages, showProgress); } + public static PDFAValidator createValidatorByFlavours(final List flavours, final int maxNumberOfDisplayedFailedChecks, + final boolean logPassedChecks, final boolean showErrorMessages, + boolean showProgress) { + if (flavours == null) { + throw new IllegalArgumentException("Parameter (List flavour) cannot be null."); + } + return createValidatorByProfiles(Profiles.getVeraProfileDirectory().getValidationProfilesByFlavours(flavours), + maxNumberOfDisplayedFailedChecks, logPassedChecks, showErrorMessages, showProgress); + } + /** * Creates a new {@link PDFAValidator} instance that uses one of the * {@link ValidationProfile}s packaged as a core library resource, see @@ -121,6 +139,15 @@ public static PDFAValidator createValidator(final PDFAFlavour flavour, final boo logPassedChecks, maxFailures, maxNumberOfDisplayedFailedChecks, showErrorMessages, showProgress); } + public static PDFAValidator createValidator(final List flavours, final boolean logPassedChecks, + final int maxFailures, final int maxNumberOfDisplayedFailedChecks, + final boolean showErrorMessages, boolean showProgress) { + if (flavours == null) + throw new IllegalArgumentException("Parameter (List flavours) cannot be null."); + return createValidatorByProfiles(Profiles.getVeraProfileDirectory().getValidationProfilesByFlavours(flavours), + logPassedChecks, maxFailures, maxNumberOfDisplayedFailedChecks, showErrorMessages, showProgress); + } + /** * Creates a new {@link PDFAValidator} initialised with the passed profile * and configured NOT to log passed checks. @@ -165,6 +192,25 @@ public static PDFAValidator createValidator(final ValidationProfile profile, fin return new BaseValidator(profile, maxNumberOfDisplayedFailedChecks, logPassedChecks, showErrorMessages, showProgress); } + public static PDFAValidator createValidator(final List profiles, final int maxNumberOfDisplayedFailedChecks, + final boolean logPassedChecks, final boolean showErrorMessages, + boolean showProgress) { + if (profiles == null) { + throw new IllegalArgumentException("Parameter (List profiles) cannot be null."); + } + return new BaseValidator(profiles, maxNumberOfDisplayedFailedChecks, logPassedChecks, showErrorMessages, showProgress); + } + + + public static PDFAValidator createValidatorByProfiles(final List profiles, final int maxNumberOfDisplayedFailedChecks, + final boolean logPassedChecks, final boolean showErrorMessages, + boolean showProgress) { + if (profiles == null) { + throw new IllegalArgumentException("Parameter (List profiles) cannot be null."); + } + return new BaseValidator(profiles, maxNumberOfDisplayedFailedChecks, logPassedChecks, showErrorMessages, showProgress); + } + /** * Creates a new {@link PDFAValidator} initialised with the passed profile, * requested fast failing behaviour and configured NOT to log passed checks. @@ -247,6 +293,19 @@ public static PDFAValidator createValidator(final ValidationProfile profile, fin return createValidator(profile, maxNumberOfDisplayedFailedChecks, logPassedChecks, showErrorMessages, showProgress); } + public static PDFAValidator createValidatorByProfiles(final List profiles, final boolean logPassedChecks, + final int maxFailures, final int maxNumberOfDisplayedFailedChecks, + boolean showErrorMessages, boolean showProgress) { + if (profiles == null) { + throw new IllegalArgumentException("Parameter (List profiles) cannot be null."); + } + if (maxFailures > 0) { + return new FastFailValidator(profiles, logPassedChecks, maxFailures, showErrorMessages, showProgress, + maxNumberOfDisplayedFailedChecks); + } + return createValidator(profiles, maxNumberOfDisplayedFailedChecks, logPassedChecks, showErrorMessages, showProgress); + } + /** * @return the default {@link ValidatorConfig} instance */ diff --git a/core/src/main/java/org/verapdf/processor/AbstractBatchHandler.java b/core/src/main/java/org/verapdf/processor/AbstractBatchHandler.java index 5730f28ae..84a5941dc 100644 --- a/core/src/main/java/org/verapdf/processor/AbstractBatchHandler.java +++ b/core/src/main/java/org/verapdf/processor/AbstractBatchHandler.java @@ -29,10 +29,7 @@ import org.verapdf.pdfa.results.ValidationResult; import org.verapdf.report.FeaturesReport; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumMap; +import java.util.*; /** * @author Carl Wilson @@ -81,7 +78,7 @@ private void processTasks(ProcessorResult result) throws VeraPDFException { switch (taskType) { case VALIDATE: if (taskResult.isSuccess()) - validationSuccess(taskResult, result.getValidationResult()); + validationSuccess(taskResult, result.getValidationResults()); else validationFailure(taskResult); break; @@ -123,7 +120,7 @@ else if (!result.isPdf()) abstract void pdfEncrypted(final TaskResult taskResult) throws VeraPDFException; - abstract void validationSuccess(final TaskResult taskResult, final ValidationResult validationResult) + abstract void validationSuccess(final TaskResult taskResult, final List validationResults) throws VeraPDFException; abstract void validationFailure(final TaskResult taskResult) throws VeraPDFException; diff --git a/core/src/main/java/org/verapdf/processor/JsonHandler.java b/core/src/main/java/org/verapdf/processor/JsonHandler.java index be651db42..917f8a924 100644 --- a/core/src/main/java/org/verapdf/processor/JsonHandler.java +++ b/core/src/main/java/org/verapdf/processor/JsonHandler.java @@ -34,11 +34,14 @@ import org.verapdf.processor.reports.BatchSummary; import org.verapdf.processor.reports.MetadataFixerReport; import org.verapdf.processor.reports.Reports; +import org.verapdf.processor.reports.ValidationReport; import org.verapdf.report.FeaturesNode; import org.verapdf.report.FeaturesReport; import java.io.IOException; import java.io.Writer; +import java.util.LinkedList; +import java.util.List; import java.util.Stack; public class JsonHandler extends AbstractBatchHandler { @@ -127,8 +130,12 @@ void pdfEncrypted(TaskResult taskResult) throws VeraPDFException { } @Override - void validationSuccess(TaskResult taskResult, ValidationResult validationResult) throws VeraPDFException { - this.serializeElement(Reports.createValidationReport(validationResult, this.logPassed), VALIDATION_RESULT); + void validationSuccess(TaskResult taskResult, List validationResults) throws VeraPDFException { + List validationReports = new LinkedList<>(); + for (ValidationResult result : validationResults) { + validationReports.add(Reports.createValidationReport(result, this.logPassed)); + } + this.serializeElement(validationReports, VALIDATION_RESULT); } @Override diff --git a/core/src/main/java/org/verapdf/processor/MrrHandler.java b/core/src/main/java/org/verapdf/processor/MrrHandler.java index 148b76800..202a4c223 100644 --- a/core/src/main/java/org/verapdf/processor/MrrHandler.java +++ b/core/src/main/java/org/verapdf/processor/MrrHandler.java @@ -37,6 +37,7 @@ import javax.xml.bind.JAXBException; import javax.xml.stream.XMLStreamException; import java.io.Writer; +import java.util.List; /** * @author Carl Wilson @@ -116,8 +117,10 @@ void pdfEncrypted(TaskResult taskResult) throws VeraPDFException { } @Override - void validationSuccess(TaskResult taskResult, ValidationResult validationResult) throws VeraPDFException { - this.serializeElement(Reports.createValidationReport(validationResult, this.logPassed), VALIDATION_RESULT, true, true); + void validationSuccess(TaskResult taskResult, List validationResults) throws VeraPDFException { + for (ValidationResult result : validationResults) { + this.serializeElement(Reports.createValidationReport(result, this.logPassed), VALIDATION_RESULT, true, true); + } } @Override diff --git a/core/src/main/java/org/verapdf/processor/ProcessorImpl.java b/core/src/main/java/org/verapdf/processor/ProcessorImpl.java index 4c6eee399..f9d281bd5 100644 --- a/core/src/main/java/org/verapdf/processor/ProcessorImpl.java +++ b/core/src/main/java/org/verapdf/processor/ProcessorImpl.java @@ -46,10 +46,7 @@ import java.io.*; import java.net.URI; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumMap; -import java.util.List; +import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -72,7 +69,7 @@ final class ProcessorImpl implements ItemProcessor { private final List errors = new ArrayList<>(); private final EnumMap taskResults = new EnumMap<>(TaskType.class); - private ValidationResult validationResult = ValidationResults.defaultResult(); + private List validationResults = Collections.singletonList(ValidationResults.defaultResult()); private FeatureExtractionResult featureResult = new FeatureExtractionResult(); private MetadataFixerResult fixerResult = new MetadataFixerResultImpl.Builder().build(); @@ -97,7 +94,7 @@ public ProcessorConfig getConfig() { private void initialise() { this.errors.clear(); this.taskResults.clear(); - this.validationResult = ValidationResults.defaultResult(); + this.validationResults = Collections.singletonList(ValidationResults.defaultResult()); this.featureResult = new FeatureExtractionResult(); this.fixerResult = new MetadataFixerResultImpl.Builder().build(); } @@ -155,7 +152,7 @@ public ProcessorResult process(File toProcess) throws VeraPDFException { TaskResultImpl.fromValues(TaskType.PARSE, parseTimer.stop(), new VeraPDFException("Caught unexpected exception during parsing", e))); //$NON-NLS-1$ } - return ProcessorResultImpl.fromValues(fileDetails, this.taskResults, this.validationResult, this.featureResult, + return ProcessorResultImpl.fromValues(fileDetails, this.taskResults, this.validationResults, this.featureResult, this.fixerResult); } @@ -210,7 +207,7 @@ public ProcessorResult process(ItemDetails fileDetails, InputStream pdfFileStrea TaskResultImpl.fromValues(TaskType.PARSE, parseTimer.stop(), new VeraPDFException("Caught unexpected exception during parsing", e))); //$NON-NLS-1$ } - return ProcessorResultImpl.fromValues(fileDetails, this.taskResults, this.validationResult, this.featureResult, + return ProcessorResultImpl.fromValues(fileDetails, this.taskResults, this.validationResults, this.featureResult, this.fixerResult); } @@ -240,9 +237,10 @@ private void validate(final PDFAParser parser) { TaskType type = TaskType.VALIDATE; Components.Timer timer = Components.Timer.start(); - try (PDFAValidator validator = validator(parser.getFlavour())) { - this.validationResult = validator.validate(parser); - this.taskResults.put(type, TaskResultImpl.fromValues(type, timer.stop())); + try (PDFAValidator validator = validator(parser.getFlavours())) { + this.validationResults = validator.validateAll(parser); + TaskResult taskResult = TaskResultImpl.fromValues(type, timer.stop()); + this.taskResults.put(type, taskResult); } catch (ValidationException excep) { logger.log(Level.WARNING, "Exception caught when validating item", excep); //$NON-NLS-1$ this.taskResults.put(type, TaskResultImpl.fromValues(type, timer.stop(), excep)); @@ -251,17 +249,17 @@ private void validate(final PDFAParser parser) { } } - private PDFAValidator validator(PDFAFlavour parsedFlavour) { - PDFAFlavour flavour = Foundries.defaultInstance().defaultFlavour(); + private PDFAValidator validator(List parsedFlavours) { + List flavours = Collections.singletonList(Foundries.defaultInstance().defaultFlavour()); if (this.isAuto()) { - if (parsedFlavour != PDFAFlavour.NO_FLAVOUR) - flavour = parsedFlavour; + if (parsedFlavours.get(0) != PDFAFlavour.NO_FLAVOUR) + flavours = parsedFlavours; } else { - flavour = this.valConf().getFlavour(); + flavours = Collections.singletonList(this.valConf().getFlavour()); } if (this.hasCustomProfile()) return foundry.createValidator(this.valConf(), this.processorConfig.getCustomProfile()); - return foundry.createValidator(this.valConf(), flavour); + return foundry.createValidator(this.valConf(), flavours); } private boolean hasCustomProfile() { @@ -283,14 +281,18 @@ private void fixMetadata(final PDFAParser parser, final String fileName) { return; } MetadataFixerResult.RepairStatus rpStat = MetadataFixerResult.RepairStatus.NO_ACTION; - try (OutputStream fxos = new BufferedOutputStream(new FileOutputStream(fxfl))) { - MetadataFixer fixer = foundry.createMetadataFixer(); - this.fixerResult = fixer.fixMetadata(parser, fxos, this.validationResult); - rpStat = this.fixerResult.getRepairStatus(); - this.taskResults.put(type, TaskResultImpl.fromValues(type, timer.stop())); - } catch (IOException excep) { - this.taskResults.put(type, TaskResultImpl.fromValues(type, timer.stop(), - new VeraPDFException("Processing exception in metadata fixer", excep))); //$NON-NLS-1$ + if (this.validationResults.size() == 1) { + try (OutputStream fxos = new BufferedOutputStream(new FileOutputStream(fxfl))) { + MetadataFixer fixer = foundry.createMetadataFixer(); + this.fixerResult = fixer.fixMetadata(parser, fxos, this.validationResults.get(0)); + rpStat = this.fixerResult.getRepairStatus(); + this.taskResults.put(type, TaskResultImpl.fromValues(type, timer.stop())); + } catch (IOException excep) { + this.taskResults.put(type, TaskResultImpl.fromValues(type, timer.stop(), + new VeraPDFException("Processing exception in metadata fixer", excep))); //$NON-NLS-1$ + } + } else { + logger.log(Level.WARNING, "Fixing metadata is not supported for several flavours."); } if (rpStat != MetadataFixerResult.RepairStatus.SUCCESS && rpStat != MetadataFixerResult.RepairStatus.ID_REMOVED) { diff --git a/core/src/main/java/org/verapdf/processor/ProcessorResult.java b/core/src/main/java/org/verapdf/processor/ProcessorResult.java index 82a917363..7f6c6dfb7 100644 --- a/core/src/main/java/org/verapdf/processor/ProcessorResult.java +++ b/core/src/main/java/org/verapdf/processor/ProcessorResult.java @@ -20,9 +20,7 @@ */ package org.verapdf.processor; -import java.util.Collection; -import java.util.EnumMap; -import java.util.EnumSet; +import java.util.*; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @@ -68,7 +66,7 @@ public interface ProcessorResult { * {@link org.verapdf.pdfa.results.ValidationResults#defaultResult()} * if validation not performed. */ - public ValidationResult getValidationResult(); + public List getValidationResults(); /** * @return the {@link FeaturesReport}. diff --git a/core/src/main/java/org/verapdf/processor/ProcessorResultImpl.java b/core/src/main/java/org/verapdf/processor/ProcessorResultImpl.java index 671736c04..fcd238b3f 100644 --- a/core/src/main/java/org/verapdf/processor/ProcessorResultImpl.java +++ b/core/src/main/java/org/verapdf/processor/ProcessorResultImpl.java @@ -20,9 +20,7 @@ */ package org.verapdf.processor; -import java.util.Collection; -import java.util.EnumMap; -import java.util.EnumSet; +import java.util.*; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; @@ -61,7 +59,7 @@ class ProcessorResultImpl implements ProcessorResult { private final ItemDetails itemDetails; private final EnumMap taskResults; @XmlElement - private final ValidationResult validationResult; + private final List validationResults; private final FeatureExtractionResult featuresResult; @XmlElement private final MetadataFixerResult fixerResult; @@ -80,19 +78,19 @@ private ProcessorResultImpl(final ItemDetails details, boolean isEncrypted, bool private ProcessorResultImpl(final ItemDetails details, boolean isValidPdf, boolean isEncrypted, boolean isOutOfMemory, final TaskResult result) { - this(details, isValidPdf, isEncrypted, isOutOfMemory, resMap(result), ValidationResults.defaultResult(), + this(details, isValidPdf, isEncrypted, isOutOfMemory, resMap(result), Collections.singletonList(ValidationResults.defaultResult()), new FeatureExtractionResult(), FixerFactory.defaultResult()); } private ProcessorResultImpl(final ItemDetails details, final EnumMap results, - final ValidationResult validationResult, final FeatureExtractionResult featuresResult, + final List validationResults, final FeatureExtractionResult featuresResult, final MetadataFixerResult fixerResult) { - this(details, true, false, false, results, validationResult, featuresResult, fixerResult); + this(details, true, false, false, results, validationResults, featuresResult, fixerResult); } private ProcessorResultImpl(final ItemDetails details, final boolean isPdf, final boolean isEncrypted, final boolean isOutOfMemory, - final EnumMap results, final ValidationResult validationResult, + final EnumMap results, final List validationResults, final FeatureExtractionResult featuresResult, final MetadataFixerResult fixerResult) { super(); this.itemDetails = details; @@ -102,7 +100,7 @@ private ProcessorResultImpl(final ItemDetails details, final boolean isPdf, fina this.taskResults = results; this.hasException = !isEncryptedPdf && !this.isOutOfMemory && this.isPdf && this.taskResults.values().stream().anyMatch(res -> res.getException() != null); - this.validationResult = validationResult; + this.validationResults = validationResults; this.featuresResult = featuresResult; this.fixerResult = fixerResult; } @@ -134,9 +132,9 @@ static ProcessorResult defaultInstance() { } static ProcessorResult fromValues(final ItemDetails details, final EnumMap results, - final ValidationResult validationResult, final FeatureExtractionResult featuresResult, - final MetadataFixerResult fixerResult) { - return new ProcessorResultImpl(details, true, false, false, results, validationResult, featuresResult, fixerResult); + final List validationResults, final FeatureExtractionResult featuresResult, + final MetadataFixerResult fixerResult) { + return new ProcessorResultImpl(details, true, false, false, results, validationResults, featuresResult, fixerResult); } static ProcessorResult invalidPdfResult(final ItemDetails details, final TaskResult res) { @@ -156,8 +154,8 @@ static ProcessorResult veraExceptionResult(final ItemDetails details, final Task } @Override - public ValidationResult getValidationResult() { - return this.validationResult; + public List getValidationResults() { + return this.validationResults; } @Override diff --git a/core/src/main/java/org/verapdf/processor/RawResultHandler.java b/core/src/main/java/org/verapdf/processor/RawResultHandler.java index 13a3150ce..67fec1b41 100644 --- a/core/src/main/java/org/verapdf/processor/RawResultHandler.java +++ b/core/src/main/java/org/verapdf/processor/RawResultHandler.java @@ -18,6 +18,7 @@ package org.verapdf.processor; import java.io.Writer; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -98,8 +99,10 @@ void pdfEncrypted(TaskResult taskResult) throws VeraPDFException { } @Override - void validationSuccess(TaskResult taskResult, ValidationResult validationResult) throws VeraPDFException { - this.serializeElement(validationResult, VALIDATION_RESULT, this.format, this.fragment); + void validationSuccess(TaskResult taskResult, List validationResults) throws VeraPDFException { + for (ValidationResult result : validationResults) { + this.serializeElement(result, VALIDATION_RESULT, this.format, this.fragment); + } } @Override diff --git a/core/src/main/java/org/verapdf/processor/SingleLineResultHandler.java b/core/src/main/java/org/verapdf/processor/SingleLineResultHandler.java index e4f0590e7..2c89bc2f8 100644 --- a/core/src/main/java/org/verapdf/processor/SingleLineResultHandler.java +++ b/core/src/main/java/org/verapdf/processor/SingleLineResultHandler.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.verapdf.core.VeraPDFException; @@ -89,17 +90,19 @@ void pdfEncrypted(final TaskResult taskResult) { } @Override - void validationSuccess(final TaskResult taskResult, final ValidationResult validationResult) + void validationSuccess(final TaskResult taskResult, final List validationResult) throws VeraPDFException { - String reportSummary = (validationResult.isCompliant() ? pass : fail) + this.item.getName() + "\n"; //$NON-NLS-1$ - try { - this.outputStreamWriter.write(reportSummary); - if (this.isVerbose || this.logSuccess) { - processRules(validationResult); + for (ValidationResult result : validationResult) { + String reportSummary = (result.isCompliant() ? pass : fail) + this.item.getName() + " " + result.getPDFAFlavour() + "\n"; //$NON-NLS-1$ + try { + this.outputStreamWriter.write(reportSummary); + if (this.isVerbose || this.logSuccess) { + processRules(result); + } + this.outputStreamWriter.flush(); + } catch (IOException excep) { + throw new VeraPDFException(ioExcepMess, excep); } - this.outputStreamWriter.flush(); - } catch (IOException excep) { - throw new VeraPDFException(ioExcepMess, excep); } } diff --git a/core/src/main/java/org/verapdf/processor/reports/Summarisers.java b/core/src/main/java/org/verapdf/processor/reports/Summarisers.java index bdafef133..0a2d87e89 100644 --- a/core/src/main/java/org/verapdf/processor/reports/Summarisers.java +++ b/core/src/main/java/org/verapdf/processor/reports/Summarisers.java @@ -3,6 +3,7 @@ */ package org.verapdf.processor.reports; +import org.verapdf.pdfa.results.ValidationResult; import org.verapdf.processor.ProcessorResult; import org.verapdf.processor.TaskResult; import org.verapdf.processor.TaskType; @@ -45,7 +46,14 @@ public ValidationSummaryBuilder addResult(final ProcessorResult result) { super.processResult(result); TaskResult taskResult = result.getResultForTask(TaskType.VALIDATE); if (taskResult != null && taskResult.isExecuted() && taskResult.isSuccess()) { - if (result.getValidationResult().isCompliant()) + boolean isCompliant = true; + for (ValidationResult res : result.getValidationResults()) { + if (!res.isCompliant()) { + isCompliant = false; + break; + } + } + if (isCompliant) this.compliant++; else this.nonCompliant++; diff --git a/core/src/main/resources/org/verapdf/report/DetailedHtmlReport.xsl b/core/src/main/resources/org/verapdf/report/DetailedHtmlReport.xsl index e93f55436..dea1c7a1d 100644 --- a/core/src/main/resources/org/verapdf/report/DetailedHtmlReport.xsl +++ b/core/src/main/resources/org/verapdf/report/DetailedHtmlReport.xsl @@ -15,7 +15,7 @@ - + @@ -88,18 +88,6 @@ }); } - - - - - - - - - - - @@ -110,31 +98,8 @@ - - - - - - - - - - - + + @@ -163,7 +128,7 @@
- Validation Profile: - - -
- Compliance: - - - Passed - - - Failed - -
- +

Statistics

@@ -201,39 +166,6 @@ - - - - - - - - - - - - - - - - - -
- Total rules in Profile: - - -
- Passed Checks: - - -
- Failed Checks: - - -
@@ -300,21 +232,8 @@
- -

Validation information

- - - - - - - -
- Rule - - Status -
+ + @@ -396,8 +315,148 @@ + + + + + + + + + + + +

Validation information

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Validation Profile: + + +
+ Compliance: + + + Passed + + + Failed + +
+ Total rules in Profile: + + +
+ Passed Checks: + + +
+ Failed Checks: + + +
+ + + + + + + + +
+ Rule + + Status +
+
+ + back to top + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ Validation Profile: + + + + +
+ Compliance: + + + Passed + + + Failed + +
+
+ + - + @@ -684,6 +743,7 @@ +
diff --git a/core/src/main/resources/org/verapdf/report/SummaryHtmlReport.xsl b/core/src/main/resources/org/verapdf/report/SummaryHtmlReport.xsl index ed211ed05..263101fed 100644 --- a/core/src/main/resources/org/verapdf/report/SummaryHtmlReport.xsl +++ b/core/src/main/resources/org/verapdf/report/SummaryHtmlReport.xsl @@ -107,7 +107,8 @@ - + +
@@ -191,11 +192,50 @@ + + + +

Job Summary

+ + + + + + + + + + + + + + + + + + + + + +
File NamePolicy CheckLogsDuration
+ + + + + + + + + + + + +
+
+ - - - -

Job Summary

+ +

Validation Summary

@@ -205,116 +245,100 @@ - - - - - - - - + + + + + + + +
File NameFailed Rules Passed Checks Failed ChecksPolicy CheckLogsDuration
+ +
+
+ + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + +