net.padaf.preflight.graphics.XObjFormValidator.java Source code

Java tutorial

Introduction

Here is the source code for net.padaf.preflight.graphics.XObjFormValidator.java

Source

/*******************************************************************************
 * Copyright 2010 Atos Worldline SAS
 * 
 * Licensed by Atos Worldline SAS under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Atos Worldline SAS 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 net.padaf.preflight.graphics;

import static net.padaf.preflight.ValidationConstants.DICTIONARY_KEY_TYPE;
import static net.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_BBOX;
import static net.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_MISSING_FIELD;
import static net.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_TRANSPARENCY_GROUP;
import static net.padaf.preflight.ValidationConstants.PATTERN_KEY_SHADING;
import static net.padaf.preflight.ValidationConstants.XOBJECT_DICTIONARY_KEY_BBOX;
import static net.padaf.preflight.ValidationConstants.XOBJECT_DICTIONARY_KEY_GROUP;
import static net.padaf.preflight.ValidationConstants.XOBJECT_DICTIONARY_KEY_GROUP_S;
import static net.padaf.preflight.ValidationConstants.XOBJECT_DICTIONARY_VALUE_S_TRANSPARENCY;

import java.util.List;

import net.padaf.preflight.DocumentHandler;
import net.padaf.preflight.ValidationConstants;
import net.padaf.preflight.ValidationException;
import net.padaf.preflight.ValidationResult.ValidationError;
import net.padaf.preflight.contentstream.ContentStreamWrapper;
import net.padaf.preflight.utils.COSUtils;

import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSStream;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectForm;

/**
 * This class validates XObject with the Form subtype.
 */
public class XObjFormValidator extends AbstractXObjValidator {
    /**
     * High level object which represents the XObjectForm
     */
    PDXObjectForm pdXObj = null;

    public XObjFormValidator(DocumentHandler handler, COSStream xobj) {
        super(handler, xobj);
        this.pdXObj = new PDXObjectForm(xobj);
    }

    /*
     * (non-Javadoc)
     * 
     * @see net.awl.edoc.pdfa.validation.graphics.AbstractXObjValidator#validate()
     */
    @Override
    public List<ValidationError> validate() throws ValidationException {
        List<ValidationError> result = super.validate();
        checkExtGraphicState(result);
        checkGroup(result);
        checkSubtype2Value(result);
        validateXObjectContent(result);
        validateShadingPattern(result);
        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @seenet.awl.edoc.pdfa.validation.graphics.AbstractXObjValidator#
     * checkMandatoryFields(java.util.List)
     */
    @Override
    protected boolean checkMandatoryFields(List<ValidationError> result) {
        boolean lastMod = this.xobject.getItem(COSName.getPDFName("LastModified")) != null;
        boolean pieceInfo = this.xobject.getItem(COSName.getPDFName("PieceInfo")) != null;
        // type and subtype checked before to create the Validator.
        if (lastMod ^ pieceInfo) {
            result.add(new ValidationError(ERROR_GRAPHIC_MISSING_FIELD));
            return false;
        }

        COSBase bbBase = this.xobject.getItem(COSName.getPDFName(XOBJECT_DICTIONARY_KEY_BBOX));
        // ---- BBox is an Array (Rectangle)
        if (bbBase == null || !COSUtils.isArray(bbBase, cosDocument)) {
            result.add(new ValidationError(ERROR_GRAPHIC_INVALID_BBOX));
            return false;
        }
        return true;
    }

    /**
     * An Form XObject is a ContentStream. This method method uses an instance of
     * ContentStreamWrapper to check the Stream of this Form XObject.
     * 
     * @param result
     *          the list of error to update if the validation fails.
     * @return true if the validation succeed, false otherwise.
     * @throws ValidationException
     */
    protected boolean validateXObjectContent(List<ValidationError> result) throws ValidationException {

        ContentStreamWrapper csWrapper = new ContentStreamWrapper(handler);
        List<ValidationError> csParseErrors = csWrapper.validXObjContentStream(pdXObj);
        if (csParseErrors == null || (csParseErrors != null && csParseErrors.isEmpty())) {
            return true;
        }

        result.addAll(csParseErrors);
        return false;
    }

    /**
     * A Form XObject may contain a Group object (Key =" Group"). If a Group
     * object is present, this method checks if the S entry is present and if its
     * value is different from "Transparency".
     * 
     * @param error
     *          the list of error to update if the validation fails.
     * @return true if the validation succeed, false otherwise
     * @throws ValidationException
     */
    protected boolean checkGroup(List<ValidationError> error) throws ValidationException {
        COSBase baseGroup = this.xobject.getItem(COSName.getPDFName(XOBJECT_DICTIONARY_KEY_GROUP));

        COSDictionary groupDictionary = COSUtils.getAsDictionary(baseGroup, cosDocument);
        if (groupDictionary != null) {
            if (!XOBJECT_DICTIONARY_KEY_GROUP.equals(groupDictionary.getNameAsString(DICTIONARY_KEY_TYPE))) {
                throw new ValidationException("The Group dictionary hasn't Group as Type value");
            }

            String sVal = groupDictionary.getNameAsString(XOBJECT_DICTIONARY_KEY_GROUP_S);
            if (sVal == null || XOBJECT_DICTIONARY_VALUE_S_TRANSPARENCY.equals(sVal)) {
                error.add(new ValidationError(ERROR_GRAPHIC_TRANSPARENCY_GROUP,
                        "Group has a transparency S entry or the S entry is null."));
                return false;
            }
        }
        return true;
    }

    /**
     * Check the Extended Graphic State contains in the Form XObject if it is
     * present. To check this ExtGState, this method uses the
     * net.awl.edoc.pdfa.validation.graphics.ExtGStateContainer object.
     * 
     * @param errors
     *          the list of error to update if the validation fails
     * @return true is the ExtGState is missing or valid, false otherwise.
     * @throws ValidationException
     */
    protected boolean checkExtGraphicState(List<ValidationError> error) throws ValidationException {
        PDResources resources = this.pdXObj.getResources();
        if (resources != null) {
            ExtGStateContainer extContainer = new ExtGStateContainer(resources.getCOSDictionary(),
                    this.cosDocument);
            return extContainer.validateTransparencyRules(error);
        }
        return true;
    }

    /**
     * This method check the Shading entry of the resource dictionary if exists.
     * To process this validation, an instance of ShadinPattern is used.
     * 
     * @param result
     *          the list of error to update if the validation fails
     * @return true if the validation succeed, false otherwise.
     * @throws ValidationException
     */
    protected boolean validateShadingPattern(List<ValidationError> result) throws ValidationException {
        PDResources resources = this.pdXObj.getResources();
        boolean res = true;
        if (resources != null) {
            COSDictionary shadings = (COSDictionary) resources.getCOSDictionary()
                    .getDictionaryObject(PATTERN_KEY_SHADING);
            if (shadings != null) {
                for (Object key : shadings.keySet()) {
                    COSDictionary aShading = (COSDictionary) shadings.getDictionaryObject((COSName) key);
                    ShadingPattern sp = new ShadingPattern(handler, aShading);
                    List<ValidationError> lErrors = sp.validate();
                    if (lErrors != null && !lErrors.isEmpty()) {
                        result.addAll(lErrors);
                        res = false;
                    }
                }
            }
        }
        return res;
    }

    /**
     * Check if there are no PS entry in the Form XObject dictionary
     * 
     * @param errors
     *          the list of error to update if the validation fails.
     * @return true if PS entry is missing, false otherwise
     */
    protected boolean checkPS(List<ValidationError> errors) {
        // 6.2.4 and 6.2.5 no PS
        if (this.xobject.getItem(COSName.getPDFName("PS")) != null) {
            errors.add(
                    new ValidationError(ValidationConstants.ERROR_GRAPHIC_UNEXPECTED_KEY, "Unexpected 'PS' Key"));
            return false;
        }
        return true;
    }

    /**
     * Check the SUbtype2 entry according to the 6.2.5 of the ISO 190005-1:2005
     * specification.
     * 
     * @param errors
     *          the list of error to update if the validation fails.
     * @return true if Subtype2 is missing or different from PS, false otherwise
     */
    protected boolean checkSubtype2Value(List<ValidationError> errors) {
        // 6.2.5 if Subtype2, value not PS
        if (this.xobject.getItem(COSName.getPDFName("Subtype2")) != null) {
            if ("PS".equals(this.xobject.getNameAsString(COSName.getPDFName("Subtype2")))) {
                errors.add(new ValidationError(ValidationConstants.ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY,
                        "Unexpected 'PS' value for 'Subtype2' Key"));
                return false;
            }
        }
        return true;
    }
}