org.apache.pdfbox.preflight.ValidationResult Maven / Gradle / Ivy
/*****************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
package org.apache.pdfbox.preflight;
import java.util.ArrayList;
import java.util.List;
import org.apache.xmpbox.XMPMetadata;
/**
* Object returned by the validate method of the PDFValidator. This object contains a boolean to know if the PDF is
* PDF/A-1x compliant. If the document isn't PDF/A-1x a list of errors is provided.
*/
public class ValidationResult
{
/**
* Boolean to know if the PDF is a valid PDF/A
*/
private boolean isValid = false;
/**
* Errors to know why the PDF isn't valid. If the PDF is valid, this list is empty.
*/
private List lErrors = new ArrayList<>();
/**
* Object representation of the XMPMetaData contained by the pdf file This attribute can be null if the Validation
* fails.
*/
private XMPMetadata xmpMetaData = null;
/**
* Create a Validation result object
*
* @param isValid
*/
public ValidationResult(boolean isValid)
{
this.isValid = isValid;
}
/**
* Create a Validation Result object. This constructor force the isValid to false and add the given error to the
* list or ValidationErrors.
*
* @param error
* if error is null, no error is added to the list.
*/
public ValidationResult(ValidationError error)
{
this.isValid = false;
if (error != null)
{
this.lErrors.add(error);
}
}
/**
* Create a Validation Result object. This constructor force the isValid to false and add all the given errors to
* the list or ValidationErrors.
*
* @param errors
* if error is null, no error is added to the list.
*/
public ValidationResult(List errors)
{
this.isValid = false;
this.lErrors = errors;
}
/**
* Add the ValidationError object of the otherResult in the Error list of the current object. Apply a logical AND on
* the isValid boolean.
*
* @param otherResult
*/
public void mergeResult(ValidationResult otherResult)
{
if (otherResult != null)
{
this.lErrors.addAll(otherResult.getErrorsList());
this.isValid &= otherResult.isValid();
}
}
/**
* @return the xmpMetaData
*/
public XMPMetadata getXmpMetaData()
{
return xmpMetaData;
}
/**
* @param xmpMetaData
* the xmpMetaData to set
*/
void setXmpMetaData(XMPMetadata xmpMetaData)
{
this.xmpMetaData = xmpMetaData;
}
/**
* @return true if the PDF is valid,false otherwise
*/
public boolean isValid()
{
return isValid;
}
/**
* Add error to the list of ValidationError. If the given error is null, this method does nothing
*
* @param error
*/
public void addError(ValidationError error)
{
if (error != null)
{
this.isValid &= error.isWarning();
this.lErrors.add(error);
}
}
/**
* Add a set of errors to the list of ValidationError. If the given list is null, this method does nothing.
*
* @param errors
*/
public void addErrors(List errors)
{
if (errors != null)
{
errors.forEach(this::addError);
}
}
/**
* @return the list of validation errors
*/
public List getErrorsList()
{
return this.lErrors;
}
/**
* This Class represents an error of validation. It contains an error code and an error explanation.
*/
public static class ValidationError
{
/**
* Error identifier. This error code can be used as identifier to internationalize the logging message using
* i18n.
*/
private final String errorCode;
/**
* Error details
*/
private String details;
/**
* false: this error can't be ignored; true: this error can be ignored
*/
private boolean isWarning = false;
// TODO Add here COSObject or the PDObject that is linked to the error may a automatic fix can be done.
/**
* Always record the place in the source code where the ValidationError
* was created, in case the ValidationError was not caused by a
* Throwable.
*/
private Throwable t = null;
/**
* Get the place where the ValidationError was created, useful if the
* ValidationError was not caused by a Throwable.
*
* @return The place where the ValidationError was created.
*/
public Throwable getThrowable()
{
return t;
}
/**
* The underlying cause if the ValidationError was caused by a Throwable.
*/
private Throwable cause = null;
/**
* The page number on which the error happened, if known.
*/
private Integer pageNumber = null;
/**
* Get the underlying cause if the ValidationError was caused by a
* Throwable.
*
* @return The underlying cause if the ValidationError was caused by a
* Throwable, or null if not.
*/
public Throwable getCause()
{
return cause;
}
/**
* Returns the page number, or null if not known.
*/
public Integer getPageNumber()
{
return pageNumber;
}
/**
* Sets or resets the page number.
*
* @param pageNumber zero based page number or null if none is known.
*/
public void setPageNumber(Integer pageNumber)
{
this.pageNumber = pageNumber;
}
/**
* Create a validation error with the given error code
*
* @param errorCode
*/
public ValidationError(String errorCode)
{
this.errorCode = errorCode;
if (errorCode.startsWith(PreflightConstants.ERROR_SYNTAX_COMMON))
{
this.details = "Syntax error";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_SYNTAX_HEADER))
{
this.details = "Header Syntax error";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_SYNTAX_BODY))
{
this.details = "Body Syntax error";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_SYNTAX_CROSS_REF))
{
this.details = "CrossRef Syntax error";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_SYNTAX_TRAILER_OUTLINES_INVALID))
{
this.details = "Outlines invalid";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_SYNTAX_TRAILER))
{
this.details = "Trailer Syntax error";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_GRAPHIC_INVALID))
{
this.details = "Invalid graphics object";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_GRAPHIC_TRANSPARENCY))
{
this.details = "Invalid graphics transparency";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY))
{
this.details = "Unexpected value for key in Graphic object definition";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_GRAPHIC_UNEXPECTED_KEY))
{
this.details = "Unexpected key in Graphic object definition";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE))
{
this.details = "Invalid Color space";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_GRAPHIC_MAIN))
{
this.details = "Unknown graphics error";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_FONTS_INVALID_DATA))
{
this.details = "Invalid Font definition";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_FONTS_DAMAGED))
{
this.details = "Font damaged";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_FONTS_GLYPH))
{
this.details = "Glyph error";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_TRANSPARENCY_EXT_GRAPHICAL_STATE))
{
this.details = "Transparency error";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_ANNOT_MISSING_FIELDS))
{
this.details = "Missing field in an annotation definition";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_ANNOT_FORBIDDEN_ELEMENT))
{
this.details = "Forbidden field in an annotation definition";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_ANNOT_INVALID_ELEMENT))
{
this.details = "Invalid field value in an annotation definition";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_ACTION_INVALID_ACTIONS))
{
this.details = "Invalid action definition";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_ACTION_FORBIDDEN_ACTIONS))
{
this.details = "Action is forbidden";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_METADATA_MAIN))
{
this.details = "Error on MetaData";
}
else if (errorCode.startsWith(PreflightConstants.ERROR_PDF_PROCESSING_MISSING))
{
this.details = "A Mandatory element is missing";
}
else
{
// default Unknown error
this.details = "Unknown error";
}
t = new Exception();
}
/**
* Create a validation error with the given error code and the error
* explanation.
*
* @param errorCode the error code
* @param details the error explanation
* @param cause the error cause
*/
public ValidationError(String errorCode, String details, Throwable cause)
{
this(errorCode);
if (details != null)
{
StringBuilder sb = new StringBuilder(this.details.length() + details.length() + 2);
sb.append(this.details).append(", ").append(details);
this.details = sb.length() > 400 ? sb.substring(0, 400) : sb.toString();
}
this.cause = cause;
t = new Exception();
}
/**
* Create a validation error with the given error code and the error
* explanation.
*
* @param errorCode the error code
* @param details the error explanation
*/
public ValidationError(String errorCode, String details)
{
this(errorCode, details, null);
}
/**
* @return the error code
*/
public String getErrorCode()
{
return errorCode;
}
/**
* @return the error explanation
*/
public String getDetails()
{
return details;
}
/**
* Set the error explanation
*
* @param details
*/
public void setDetails(String details)
{
this.details = details;
}
public boolean isWarning()
{
return isWarning;
}
public void setWarning(boolean isWarning)
{
this.isWarning = isWarning;
}
@Override
public int hashCode()
{
return errorCode.hashCode();
}
@Override
public boolean equals(Object o)
{
if (o instanceof ValidationError)
{
ValidationError ve = (ValidationError) o;
// check errorCode
if (!errorCode.equals(ve.errorCode))
{
return false;
}
else if (!details.equals(ve.details))
{
return false;
}
else if (pageNumber != null && ve.pageNumber == null)
{
return false;
}
else if (pageNumber == null && ve.pageNumber != null)
{
return false;
}
else if (pageNumber != null && ve.pageNumber != null
&& pageNumber.compareTo(ve.pageNumber) != 0)
{
return false;
}
// check warning
return isWarning == ve.isWarning;
}
else
{
return false;
}
}
}
}