refactor(service): make validation methods non-static in VeraPDFService

- Changed `validatePDF` and `validateAllDeclaredStandards` methods from static to instance methods
- Updated comments to include explicit null checks for better NPE prevention in warning logic

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
This commit is contained in:
Balázs Szücs 2025-11-14 21:36:21 +01:00
parent b733dae1af
commit 525864ff2c

View File

@ -61,90 +61,37 @@ public class VeraPDFService {
} }
} }
public static PDFVerificationResult validatePDF(InputStream pdfStream, String standardString) private static boolean isWarningByMessage(String message) {
throws IOException, ValidationException, ModelParsingException, EncryptedPdfException { // Check for null or blank message - explicit null check is necessary to avoid NPE
if (message == null || message.isBlank()) {
byte[] pdfBytes = pdfStream.readAllBytes(); return false;
PDFAFlavour validationFlavour = PDFAFlavour.fromString(standardString);
Optional<PDFAFlavour> declaredPdfaFlavour = extractDeclaredPdfaFlavour(pdfBytes);
try (PDFAParser parser =
Foundries.defaultInstance()
.createParser(new ByteArrayInputStream(pdfBytes), validationFlavour)) {
PDFAValidator validator =
Foundries.defaultInstance().createValidator(validationFlavour, false);
ValidationResult result = validator.validate(parser);
return convertToVerificationResult(
result, declaredPdfaFlavour.orElse(null), validationFlavour);
} }
String normalized = message.toLowerCase(Locale.ROOT);
return normalized.contains("recommended")
|| normalized.contains("should")
|| normalized.contains("optional")
|| normalized.contains("missing recommended");
} }
public static List<PDFVerificationResult> validateAllDeclaredStandards(InputStream pdfStream) private static boolean isWarningByClause(String clause) {
throws IOException, ValidationException, ModelParsingException, EncryptedPdfException { // Check for null or blank clause - explicit null check is necessary to avoid NPE
if (clause == null || clause.isBlank()) {
byte[] pdfBytes = pdfStream.readAllBytes(); return false;
Optional<PDFAFlavour> declaredPdfaFlavour = extractDeclaredPdfaFlavour(pdfBytes);
List<PDFVerificationResult> results = new ArrayList<>();
List<PDFAFlavour> detectedFlavours;
try (PDFAParser detectionParser =
Foundries.defaultInstance().createParser(new ByteArrayInputStream(pdfBytes))) {
detectedFlavours = detectionParser.getFlavours();
} }
List<PDFAFlavour> flavoursToValidate = new ArrayList<>(); if (clause.startsWith("6.7")) {
return true;
}
declaredPdfaFlavour.ifPresent(flavoursToValidate::add); for (String criticalPrefix : CRITICAL_CLAUSE_PREFIXES) {
if (clause.startsWith(criticalPrefix)) {
for (PDFAFlavour flavour : detectedFlavours) { return false;
if (PDFFlavours.isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.PDF_A)) {
if (declaredPdfaFlavour.isPresent() && !declaredPdfaFlavour.get().equals(flavour)) {
flavoursToValidate.add(flavour);
} else if (declaredPdfaFlavour.isEmpty()) {
log.debug(
"Ignoring detected PDF/A flavour {} because no PDF/A declaration exists in XMP",
flavour.getId());
}
} else if (PDFFlavours.isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.PDF_UA)
|| PDFFlavours.isFlavourFamily(
flavour, PDFAFlavour.SpecificationFamily.WTPDF)) {
flavoursToValidate.add(flavour);
} }
} }
if (declaredPdfaFlavour.isEmpty()) { return true;
results.add(createNoPdfaDeclarationResult());
}
if (flavoursToValidate.isEmpty()) {
log.info("No verifiable PDF/A, PDF/UA, or WTPDF standards declared via XMP metadata");
return results;
}
for (PDFAFlavour flavour : flavoursToValidate) {
try (PDFAParser parser =
Foundries.defaultInstance()
.createParser(new ByteArrayInputStream(pdfBytes), flavour)) {
PDFAValidator validator =
Foundries.defaultInstance().createValidator(flavour, false);
ValidationResult result = validator.validate(parser);
PDFAFlavour declaredForResult =
PDFFlavours.isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.PDF_A)
? declaredPdfaFlavour.orElse(null)
: flavour;
results.add(convertToVerificationResult(result, declaredForResult, flavour));
} catch (Exception e) {
log.error("Error validating standard {}: {}", flavour.getId(), e.getMessage());
results.add(
buildErrorResult(
declaredPdfaFlavour,
flavour,
"Validation error: " + e.getMessage()));
}
}
return results;
} }
private static PDFVerificationResult convertToVerificationResult( private static PDFVerificationResult convertToVerificationResult(
@ -264,37 +211,90 @@ public class VeraPDFService {
return ruleId != null && WARNING_RULES.contains(ruleId); return ruleId != null && WARNING_RULES.contains(ruleId);
} }
private static boolean isWarningByMessage(String message) { public PDFVerificationResult validatePDF(InputStream pdfStream, String standardString)
// isBlank() already handles null and empty strings throws IOException, ValidationException, ModelParsingException, EncryptedPdfException {
if (message == null || message.isBlank()) {
return false; byte[] pdfBytes = pdfStream.readAllBytes();
PDFAFlavour validationFlavour = PDFAFlavour.fromString(standardString);
Optional<PDFAFlavour> declaredPdfaFlavour = extractDeclaredPdfaFlavour(pdfBytes);
try (PDFAParser parser =
Foundries.defaultInstance()
.createParser(new ByteArrayInputStream(pdfBytes), validationFlavour)) {
PDFAValidator validator =
Foundries.defaultInstance().createValidator(validationFlavour, false);
ValidationResult result = validator.validate(parser);
return convertToVerificationResult(
result, declaredPdfaFlavour.orElse(null), validationFlavour);
} }
String normalized = message.toLowerCase(Locale.ROOT);
return normalized.contains("recommended")
|| normalized.contains("should")
|| normalized.contains("optional")
|| normalized.contains("missing recommended");
} }
private static boolean isWarningByClause(String clause) { public List<PDFVerificationResult> validateAllDeclaredStandards(InputStream pdfStream)
// isBlank() already handles null and empty strings throws IOException, ValidationException, ModelParsingException, EncryptedPdfException {
if (clause == null || clause.isBlank()) {
return false; byte[] pdfBytes = pdfStream.readAllBytes();
Optional<PDFAFlavour> declaredPdfaFlavour = extractDeclaredPdfaFlavour(pdfBytes);
List<PDFVerificationResult> results = new ArrayList<>();
List<PDFAFlavour> detectedFlavours;
try (PDFAParser detectionParser =
Foundries.defaultInstance().createParser(new ByteArrayInputStream(pdfBytes))) {
detectedFlavours = detectionParser.getFlavours();
} }
if (clause.startsWith("6.7")) { List<PDFAFlavour> flavoursToValidate = new ArrayList<>();
return true;
}
for (String criticalPrefix : CRITICAL_CLAUSE_PREFIXES) { declaredPdfaFlavour.ifPresent(flavoursToValidate::add);
if (clause.startsWith(criticalPrefix)) {
return false; for (PDFAFlavour flavour : detectedFlavours) {
if (PDFFlavours.isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.PDF_A)) {
if (declaredPdfaFlavour.isPresent() && !declaredPdfaFlavour.get().equals(flavour)) {
flavoursToValidate.add(flavour);
} else if (declaredPdfaFlavour.isEmpty()) {
log.debug(
"Ignoring detected PDF/A flavour {} because no PDF/A declaration exists in XMP",
flavour.getId());
}
} else if (PDFFlavours.isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.PDF_UA)
|| PDFFlavours.isFlavourFamily(
flavour, PDFAFlavour.SpecificationFamily.WTPDF)) {
flavoursToValidate.add(flavour);
} }
} }
return true; if (declaredPdfaFlavour.isEmpty()) {
results.add(createNoPdfaDeclarationResult());
}
if (flavoursToValidate.isEmpty()) {
log.info("No verifiable PDF/A, PDF/UA, or WTPDF standards declared via XMP metadata");
return results;
}
for (PDFAFlavour flavour : flavoursToValidate) {
try (PDFAParser parser =
Foundries.defaultInstance()
.createParser(new ByteArrayInputStream(pdfBytes), flavour)) {
PDFAValidator validator =
Foundries.defaultInstance().createValidator(flavour, false);
ValidationResult result = validator.validate(parser);
PDFAFlavour declaredForResult =
PDFFlavours.isFlavourFamily(flavour, PDFAFlavour.SpecificationFamily.PDF_A)
? declaredPdfaFlavour.orElse(null)
: flavour;
results.add(convertToVerificationResult(result, declaredForResult, flavour));
} catch (Exception e) {
log.error("Error validating standard {}: {}", flavour.getId(), e.getMessage());
results.add(
buildErrorResult(
declaredPdfaFlavour,
flavour,
"Validation error: " + e.getMessage()));
}
}
return results;
} }
private static PDFVerificationResult createNoPdfaDeclarationResult() { private static PDFVerificationResult createNoPdfaDeclarationResult() {