Example usage for org.apache.pdfbox.cos COSArray get

List of usage examples for org.apache.pdfbox.cos COSArray get

Introduction

In this page you can find the example usage for org.apache.pdfbox.cos COSArray get.

Prototype

public COSBase get(int index) 

Source Link

Document

This will get an object from the array.

Usage

From source file:com.esri.geoportal.commons.pdf.PdfUtils.java

License:Apache License

/**
 * Extracts the geospatial metadata from a GeoPDF
 * /*from ww  w.j  a  v a  2  s . c  o  m*/
 * @param page the PDF page to read geospatial metadata from
 * @param geometryServiceUrl url of a <a href="https://developers.arcgis.com/rest/services-reference/geometry-service.htm">geometry service</a> for reprojecting coordinates. 
 * 
 * @see <a href="https://www.loc.gov/preservation/digital/formats/fdd/fdd000312.shtml">Library of Congress information on GeoPDF</a>
 * @see <a href="https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf">The PDF specification</a>, section 8, for instructions for translating coordinates.
 * 
 * @returns the bounding box of the GeoPDF as "yMin xMin, yMax xMax"
 */
private static String extractGeoPDFProps(PDPage page, String geometryServiceUrl) {

    // The LGI dictionary is an array, we'll loop through all entries and pull the first one for a bounding box
    COSArray lgi = (COSArray) page.getCOSObject().getDictionaryObject("LGIDict");

    List<String> bBoxes = new ArrayList<>();

    lgi.iterator().forEachRemaining(item -> {

        String currentBbox = null;

        // Set up the Coordinate Transformation Matrix (used to translate PDF coords to geo coords)
        Double[][] ctmValues = null;

        COSDictionary dictionary = (COSDictionary) item;
        if (dictionary.containsKey("CTM")) {
            ctmValues = new Double[3][3];

            // The last column in the matrix is always constant
            ctmValues[0][2] = 0.0;
            ctmValues[1][2] = 0.0;
            ctmValues[2][2] = 1.0;

            COSArray ctm = (COSArray) dictionary.getDictionaryObject("CTM");
            for (int i = 0; i < ctm.toList().size(); i += 2) {
                int ctmRow = i / 2;
                ctmValues[ctmRow][0] = Double.parseDouble(((COSString) ctm.get(i)).getString());
                ctmValues[ctmRow][1] = Double.parseDouble(((COSString) ctm.get(i + 1)).getString());
            }
        }

        // Get the neatline (i.e. the bounding box in *PDF* coordinates)
        Double[][] neatLineValues = null;
        int neatLineLength = 0;
        if (dictionary.containsKey("Neatline")) {

            COSArray neatline = (COSArray) dictionary.getDictionaryObject("Neatline");
            neatLineLength = neatline.toList().size();
            neatLineValues = new Double[neatLineLength / 2][3];

            for (int i = 0; i < neatline.toList().size(); i += 2) {
                int neatLineRow = i / 2;
                neatLineValues[neatLineRow][0] = Double.parseDouble(((COSString) neatline.get(i)).getString());
                neatLineValues[neatLineRow][1] = Double
                        .parseDouble(((COSString) neatline.get(i + 1)).getString());
                neatLineValues[neatLineRow][2] = 1.0;
            }
        }

        // Translate the PDF coordinates to Geospatial coordintates by multiplying the two matricies
        MultiPoint mp = new MultiPoint();
        if (ctmValues != null && neatLineValues != null) {
            Double[][] resultCoords = new Double[neatLineLength / 2][3];
            for (int z = 0; z < neatLineLength / 2; z++) {
                for (int i = 0; i < 3; i++) {
                    resultCoords[z][i] = neatLineValues[z][0] * ctmValues[0][i]
                            + neatLineValues[z][1] * ctmValues[1][i] + neatLineValues[z][2] * ctmValues[2][i];
                }
                mp.add(resultCoords[z][0], resultCoords[z][1]);
            }
        }

        // Project the geospatial coordinates to WGS84 for the Dublin-Core metadata
        if (dictionary.containsKey("Projection")) {
            COSDictionary projectionDictionary = (COSDictionary) dictionary.getDictionaryObject("Projection");
            String projectionType = projectionDictionary.getString("ProjectionType");

            try (GeometryService svc = new GeometryService(HttpClients.custom().useSystemProperties().build(),
                    new URL(geometryServiceUrl));) {

                // UTM projections require slightly different processing
                if ("UT".equals(projectionType)) {
                    String zone = Integer.toString(projectionDictionary.getInt("Zone"));
                    String hemisphere = projectionDictionary.getString("Hemisphere");

                    // Get the wkt for the geospatial coordinate system
                    String wkt = datumTranslation(projectionDictionary.getItem("Datum"));

                    if (zone != null && hemisphere != null && wkt != null) {
                        // Generate a list of UTM strings
                        List<String> utmCoords = new ArrayList<>();
                        for (Point2D pt : mp.getCoordinates2D()) {
                            String coord = String.format("%s%s %s %s", zone, hemisphere, Math.round(pt.x),
                                    Math.round(pt.y));
                            utmCoords.add(coord);
                        }

                        MultiPoint reproj = svc.fromGeoCoordinateString(utmCoords, WGS84_WKID);

                        currentBbox = generateBbox(reproj);

                    } else {
                        LOG.warn("Missing UTM argument: zone: {}, hemisphere: {}, datum: {}", zone, hemisphere,
                                wkt);
                        LOG.debug("Projection dictionary {}", projectionDictionary);
                    }
                } else {
                    // Generate Well Known Text for projection and re-projects the points to WGS 84
                    String wkt = getProjectionWKT(projectionDictionary, projectionType);

                    if (wkt != null) {
                        MultiPoint reproj = svc.project(mp, wkt, WGS84_WKID);

                        currentBbox = generateBbox(reproj);

                    } else if (LOG.isDebugEnabled()) {
                        // Print out translated coordinates for debugging purposes
                        LOG.debug("Translated Coordinates");
                        for (Point2D pt : mp.getCoordinates2D()) {
                            LOG.debug(String.format("\t%s, %s", pt.x, pt.y));
                        }
                    }
                }
            } catch (Exception e) {
                // If something goes wrong, just try the next set of coordinates
                LOG.error("Exception reprojecting geometry, skipping this geopdf dictionary instance...", e);
            }
        }

        if (currentBbox != null) {
            bBoxes.add(currentBbox);
        }

    });

    return bBoxes.get(0);
}

From source file:com.santaanna.friendlyreader.pdfstod.pdfstod3.ReplaceStringStreamEngine.java

License:Apache License

public COSArray arraycopy(COSArray carr) {
    COSArray retcarr = new COSArray();
    for (int cind = 0; cind < carr.size(); cind++) {
        retcarr.add(carr.get(cind));
    }/*w ww. j a  v  a 2  s  .com*/
    return retcarr;
}

From source file:ddf.catalog.transformer.input.pdf.GeoPdfParserImpl.java

License:Open Source License

/**
 * Parses a given NeatLine and Transformation matrix into a WKT String
 *
 * @param lgidict         - The PDF's LGIDict object
 * @param neatLineArray   - The NeatLine array of points for the PDF
 * @param toDoubleVisitor - A visitor that converts PDF Strings / Ints / Longs into doubles.
 * @return the generated WKT Lat/Lon set
 * @throws IOException/*from   w  ww  .j a v a2s .c  om*/
 */
private String getWktFromNeatLine(COSDictionary lgidict, COSArray neatLineArray, ICOSVisitor toDoubleVisitor)
        throws IOException {
    List<Double> neatline = new LinkedList<>();
    List<String> coordinateList = new LinkedList<>();
    String firstCoordinate = null;

    double[] points = new double[CTM_SIZE];
    for (int i = 0; i < CTM_SIZE; i++) {
        points[i] = (Double) lgidict.getObjectFromPath(CTM + "/[" + i + "]").accept(toDoubleVisitor);
    }
    AffineTransform affineTransform = new AffineTransform(points);

    for (int i = 0; i < neatLineArray.size(); i++) {
        neatline.add((Double) neatLineArray.get(i).accept(toDoubleVisitor));
    }

    for (int i = 0; i < neatline.size(); i += 2) {
        double x = neatline.get(i);
        double y = neatline.get(i + 1);

        Point2D p = new Point2D.Double(x, y);

        Point2D pprime = affineTransform.transform(p, null);

        String xySet = point2dToWkt(pprime);

        if (firstCoordinate == null) {
            firstCoordinate = xySet;
        }
        coordinateList.add(xySet);
    }
    coordinateList.add(firstCoordinate);
    String wktString = StringUtils.join(coordinateList, ", ");
    LOGGER.debug("{}", wktString);
    return wktString.toString();
}

From source file:net.padaf.preflight.actions.ActionManagerFactory.java

License:Apache License

/**
 * Returns all actions contained by the Next entry. If the action dictionary
 * doesn't have Next action, the result is an empty list.
 * //from w  w  w . ja va 2 s  .c o m
 * @param actionDictionary
 *          the action dictionary which contains Next entry
 * @param cDoc
 *          the COSDocument which contains actions.
 * @return
 * @throws ValidationException
 */
public final List<AbstractActionManager> getNextActions(COSDictionary actionDictionary, COSDocument cDoc)
        throws ValidationException {
    List<AbstractActionManager> result = new ArrayList<AbstractActionManager>(0);
    Map<COSObjectKey, Boolean> alreadyCreated = new HashMap<COSObjectKey, Boolean>();

    COSBase nextDict = actionDictionary.getDictionaryObject(ACTION_DICTIONARY_KEY_NEXT);
    if (nextDict != null) {
        if (COSUtils.isArray(nextDict, cDoc)) {
            COSArray array = COSUtils.getAsArray(nextDict, cDoc);
            // ---- Next may contains an array of Action dictionary
            for (int i = 0; i < array.size(); ++i) {
                callCreateAction(array.get(i), cDoc, result, alreadyCreated);
            }
        } else {
            // ---- Next field contains a Dictionary or a reference to a Dictionary
            callCreateAction(nextDict, cDoc, result, alreadyCreated);
        }
    }
    return result;
}

From source file:net.padaf.preflight.font.CompositeFontValidator.java

License:Apache License

/**
 * This method validates the CIDFont dictionary.
 * /*from w  w  w . j a  v a2s . c  o  m*/
 * This method returns false and updates the list of errors in the
 * FontContainer if some mandatory fields are missing.
 * 
 * This method calls the processCIDFontTypeX method to check if the font is
 * damaged or not. If the font is damaged, the errors list is updated and the
 * method return false.
 * 
 * @return
 * @throws ValidationException
 */
protected boolean checkCIDFont() throws ValidationException {

    // ---- a CIDFont is contained in the DescendantFonts array
    COSDocument cDoc = this.handler.getDocument().getDocument();
    COSArray array = COSUtils.getAsArray(descendantFonts, cDoc);

    if (array == null) {
        this.fontContainer.addError(new ValidationError(ERROR_FONTS_CIDKEYED_INVALID,
                "CIDFont is missing from the DescendantFonts array"));
        return false;
    }
    // ---- in PDF 1.4, this array must contain only one element,
    // because of a PDF/A should be a PDF 1.4, this method returns an error if
    // the array
    // has more than one element.
    if (array.size() != 1) {
        this.fontContainer.addError(new ValidationError(ERROR_FONTS_CIDKEYED_INVALID,
                "The DescendantFonts array should have one element."));
        return false;
    }

    this.cidFont = COSUtils.getAsDictionary(array.get(0), cDoc);
    if (this.cidFont == null) {
        this.fontContainer.addError(new ValidationError(ERROR_FONTS_CIDKEYED_INVALID,
                "The DescendantFonts array should have one element with is a dictionary."));
        return false;
    }

    String type = cidFont.getNameAsString(COSName.getPDFName(DICTIONARY_KEY_TYPE));
    String subtype = cidFont.getNameAsString(COSName.getPDFName(DICTIONARY_KEY_SUBTYPE));

    if ((type == null || "".equals(type)) || (subtype == null || "".equals(subtype))) {
        this.fontContainer.addError(
                new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "Type and/or Subtype keys are missing"));
        return false;
    }

    boolean isT0 = FONT_DICTIONARY_VALUE_TYPE0.equals(subtype);
    boolean isT2 = FONT_DICTIONARY_VALUE_TYPE2.equals(subtype);
    // ---- Even if these entries are present, values must be checked.
    if (!FONT_DICTIONARY_VALUE_FONT.equals(type) || !(isT0 || isT2)) {
        this.fontContainer.addError(
                new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "Type and/or Subtype keys are missing"));
        return false;
    }

    // ---- BaseFont is mandatory
    String bf = cidFont.getNameAsString(COSName.getPDFName(FONT_DICTIONARY_KEY_BASEFONT));
    if (bf == null || "".equals(bf)) {
        this.fontContainer.addError(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "BaseFont is missing"));
        return false;
    }

    // ---- checks others mandatory fields
    COSBase sysinfo = cidFont.getItem(COSName.getPDFName(FONT_DICTIONARY_KEY_CID_SYSINFO));
    COSBase fontDesc = cidFont.getItem(COSName.getPDFName(FONT_DICTIONARY_KEY_FONT_DESC));
    COSBase cidToGid = cidFont.getItem(COSName.getPDFName(FONT_DICTIONARY_KEY_CID_GIDMAP));

    boolean result = checkCIDSystemInfo(sysinfo, cDoc);
    if (isT0) {
        result = result && checkCIDToGIDMap(cidToGid, cDoc, false);
        result = result && processCIDFontType0(fontDesc);
    } else {
        result = result && checkCIDToGIDMap(cidToGid, cDoc, true);
        result = result && processCIDFontType2(fontDesc);
    }
    return result;
}

From source file:net.padaf.preflight.font.Type3FontValidator.java

License:Apache License

/**
 * FontBBox and FontMatrix are required. This method checks the type and the
 * content of the FontBBox and FontMatrix element (Array of 4/6 number). If a
 * type is invalid, the FontContainer is updated and the method returns false.
 * /*from  w w  w  . j  a  v a  2  s  .  co m*/
 * @return
 */
private boolean checkFontBBoxMatrix() {
    COSDocument cDoc = this.handler.getDocument().getDocument();

    // ---- both elements are an array
    if (!COSUtils.isArray(this.fontBBox, cDoc)) {
        this.fontContainer.addError(
                new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "The FontBBox element isn't an array"));
        return false;
    }

    if (!COSUtils.isArray(this.fontMatrix, cDoc)) {
        this.fontContainer.addError(
                new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "The FontMatrix element isn't an array"));
        return false;
    }

    // ---- check the content of the FontBBox.
    // ---- Should be an array with 4 numbers
    COSArray bbox = COSUtils.getAsArray(fontBBox, cDoc);
    if (bbox.size() != 4) {
        this.fontContainer.addError(
                new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "The FontBBox element is invalid"));
        return false;
    } else {
        for (int i = 0; i < 4; i++) {
            COSBase elt = bbox.get(i);
            if (!(COSUtils.isFloat(elt, cDoc) || COSUtils.isInteger(elt, cDoc))) {
                this.fontContainer.addError(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
                        "An element of FontBBox isn't a number"));
                return false;
            }
        }
    }

    // ---- check the content of the FontMatrix.
    // ---- Should be an array with 6 numbers
    COSArray matrix = COSUtils.getAsArray(fontMatrix, cDoc);
    if (matrix.size() != 6) {
        this.fontContainer.addError(
                new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "The FontMatrix element is invalid"));
        return false;
    } else {
        for (int i = 0; i < 6; i++) {
            COSBase elt = matrix.get(i);
            if (!(COSUtils.isFloat(elt, cDoc) || COSUtils.isInteger(elt, cDoc))) {
                this.fontContainer.addError(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
                        "An element of FontMatrix isn't a number"));
                return false;
            }
        }
    }

    return true;
}

From source file:net.padaf.preflight.font.Type3FontValidator.java

License:Apache License

/**
 * For a Type3 font, the mapping between the Character Code and the Character
 * name is entirely defined in the Encoding Entry. The Encoding Entry can be a
 * Name (For the 5 predefined Encoding) or a Dictionary. If it is a
 * dictionary, the "Differences" array contains the correspondence between a
 * character code and a set of character name which are different from the
 * encoding entry of the dictionary./*from  w  w w.  j  a v  a  2s. c o m*/
 * 
 * This method checks that the encoding is :
 * <UL>
 * <li>An existing encoding name.
 * <li>A dictionary with an existing encoding name (the name is optional) and
 * a well formed "Differences" array (the array is optional)
 * </UL>
 * 
 * @return
 */
private boolean checkEncoding() {
    COSDocument cDoc = this.handler.getDocument().getDocument();

    EncodingManager emng = new EncodingManager();
    if (COSUtils.isString(this.fontEncoding, cDoc)) {
        // ---- Encoding is a Name, check if it is an Existing Encoding
        String enc = COSUtils.getAsString(this.fontEncoding, cDoc);
        try {
            type3Encoding = emng.getEncoding(COSName.getPDFName(enc));
        } catch (IOException e) {
            // ---- the encoding doesn't exist
            this.fontContainer.addError(new ValidationError(ERROR_FONTS_ENCODING));
            return false;
        }
    } else if (COSUtils.isDictionary(this.fontEncoding, cDoc)) {
        COSDictionary encodingDictionary = COSUtils.getAsDictionary(this.fontEncoding, cDoc);
        try {
            type3Encoding = new DictionaryEncoding(encodingDictionary);
        } catch (IOException e) {
            // ---- the encoding doesn't exist
            this.fontContainer.addError(new ValidationError(ERROR_FONTS_ENCODING));
            return false;
        }

        COSBase diff = encodingDictionary.getItem(COSName.getPDFName(FONT_DICTIONARY_KEY_DIFFERENCES));
        if (diff != null) {
            if (!COSUtils.isArray(diff, cDoc)) {
                this.fontContainer.addError(new ValidationError(ERROR_FONTS_TYPE3_DAMAGED,
                        "The differences element of the encoding dictionary isn't an array"));
                return false;
            }

            // ---- The DictionaryEncoding object doesn't throw exception if the
            // Differences isn't well formed.
            // So check if the array has the right format.
            COSArray differences = COSUtils.getAsArray(diff, cDoc);
            for (int i = 0; i < differences.size(); ++i) {
                COSBase item = differences.get(i);
                if (!(item instanceof COSInteger || item instanceof COSName)) {
                    // ---- Error, the Differences array is invalid
                    this.fontContainer.addError(new ValidationError(ERROR_FONTS_TYPE3_DAMAGED,
                            "Differences Array should contain COSInt or COSName, no other type"));
                    return false;
                }
            }
        }
    } else {
        // ---- the encoding entry is invalid
        this.fontContainer.addError(new ValidationError(ERROR_FONTS_TYPE3_DAMAGED,
                "The Encoding entry doesn't have the right type"));
        return false;
    }

    return true;
}

From source file:net.padaf.preflight.font.Type3FontValidator.java

License:Apache License

/**
 * CharProcs is a dictionary where the key is a character name and the value
 * is a Stream which contains the glyph representation of the key.
 * /*from w w w . ja  va 2  s.  co m*/
 * This method checks that all character code defined in the Widths Array
 * exist in the CharProcs dictionary. If the CharProcs doesn't know the
 * Character, it is mapped with the .notdef one.
 * 
 * For each character, the Glyph width must be the same as the Width value
 * declared in the Widths array.
 * 
 * @param errors
 * @return
 */
private boolean checkCharProcsAndMetrics() throws ValidationException {
    COSDocument cDoc = this.handler.getDocument().getDocument();

    // ---- the Widths value can be a reference to an object
    // ---- Access the object using the COSkey
    COSArray wArr = COSUtils.getAsArray(this.widths, cDoc);
    if (wArr == null) {
        this.fontContainer.addError(
                new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "The Witdhs array is unreachable"));
        return false;
    }

    COSDictionary charProcsDictionary = COSUtils.getAsDictionary(this.charProcs, cDoc);
    if (charProcsDictionary == null) {
        this.fontContainer.addError(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
                "The CharProcs element isn't a dictionary"));
        return false;
    }

    // ---- firstChar and lastChar must be integer.
    int fc = ((COSInteger) this.firstChar).intValue();
    int lc = ((COSInteger) this.lastChar).intValue();

    // ---- wArr length = (lc - fc) +1 and it is an array of int.
    // ---- If FirstChar is greater than LastChar, the validation will fail
    // because of
    // ---- the array will have an expected size <= 0.
    int expectedLength = (lc - fc) + 1;
    if (wArr.size() != expectedLength) {
        this.fontContainer.addError(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
                "The length of Witdhs array is invalid. Expected : \"" + expectedLength + "\" Current : \""
                        + wArr.size() + "\""));
        return false;
    }

    // ---- Check width consistency
    for (int i = 0; i < expectedLength; i++) {
        int cid = fc + i;
        COSBase arrContent = wArr.get(i);
        if (COSUtils.isNumeric(arrContent, cDoc)) {
            float width = COSUtils.getAsFloat(arrContent, cDoc);

            String charName = null;
            try {
                charName = this.type3Encoding.getName(cid);
            } catch (IOException e) {
                // shouldn't occur
                throw new ValidationException("Unable to check Widths consistency", e);
            }

            COSBase item = charProcsDictionary.getItem(COSName.getPDFName(charName));
            COSStream charStream = COSUtils.getAsStream(item, cDoc);
            if (charStream == null && width != 0) {
                GlyphException glyphEx = new GlyphException(ERROR_FONTS_METRICS, cid,
                        "The CharProcs \"" + charName + "\" doesn't exist but the width is " + width);
                GlyphDetail glyphDetail = new GlyphDetail(cid, glyphEx);
                this.fontContainer.addKnownCidElement(glyphDetail);
            } else {
                try {
                    // --- Parse the Glyph description to obtain the Width
                    PDFAType3StreamParser parser = new PDFAType3StreamParser(this.handler);
                    PDResources pRes = null;
                    if (this.resources != null) {
                        COSDictionary resAsDict = COSUtils.getAsDictionary(this.resources, cDoc);
                        if (resAsDict != null) {
                            pRes = new PDResources(resAsDict);
                        }
                    }
                    parser.resetEngine();
                    parser.processSubStream(null, pRes, charStream);

                    if (width != parser.getWidth()) {
                        GlyphException glyphEx = new GlyphException(ERROR_FONTS_METRICS, cid,
                                "The CharProcs \"" + charName + "\" should have a width equals to " + width);
                        GlyphDetail glyphDetail = new GlyphDetail(cid, glyphEx);
                        this.fontContainer.addKnownCidElement(glyphDetail);
                    } else {
                        // Glyph is OK, we keep the CID.
                        GlyphDetail glyphDetail = new GlyphDetail(cid);
                        this.fontContainer.addKnownCidElement(glyphDetail);
                    }
                } catch (ContentStreamException e) {
                    this.fontContainer.addError(new ValidationError(e.getValidationError()));
                    return false;
                } catch (IOException e) {
                    this.fontContainer.addError(new ValidationError(ERROR_FONTS_TYPE3_DAMAGED,
                            "The CharProcs references an element which can't be read"));
                    return false;
                }
            }

        } else {
            this.fontContainer.addError(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
                    "The Witdhs array is invalid. (some element aren't integer)"));
            return false;
        }
    }
    return true;
}

From source file:net.padaf.preflight.helpers.CatalogValidationHelper.java

License:Apache License

/**
 * This method checks the content of each OutputIntent. The S entry must
 * contain GTS_PDFA1. The DestOuputProfile must contain a valid ICC Profile
 * Stream./* w  w  w. j  a v  a2s.  c o m*/
 * 
 * If there are more than one OutputIntent, they have to use the same ICC
 * Profile.
 * 
 * This method returns a list of ValidationError. It is empty if no errors
 * have been found.
 * 
 * @param handler
 * @return
 * @throws ValidationException
 */
public List<ValidationError> validateOutputIntent(DocumentHandler handler) throws ValidationException {
    List<ValidationError> result = new ArrayList<ValidationError>(0);
    PDDocument pdDocument = handler.getDocument();
    PDDocumentCatalog catalog = pdDocument.getDocumentCatalog();
    COSDocument cDoc = pdDocument.getDocument();

    COSBase cBase = catalog.getCOSDictionary()
            .getItem(COSName.getPDFName(DOCUMENT_DICTIONARY_KEY_OUTPUT_INTENTS));
    COSArray outputIntents = COSUtils.getAsArray(cBase, cDoc);

    Map<COSObjectKey, Boolean> tmpDestOutputProfile = new HashMap<COSObjectKey, Boolean>();

    for (int i = 0; outputIntents != null && i < outputIntents.size(); ++i) {
        COSDictionary dictionary = COSUtils.getAsDictionary(outputIntents.get(i), cDoc);

        if (dictionary == null) {

            result.add(new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
                    "OutputIntent object is null or isn't a dictionary"));

        } else {
            // ---- S entry is mandatory and must be equals to GTS_PDFA1
            String sValue = dictionary.getNameAsString(COSName.getPDFName(OUTPUT_INTENT_DICTIONARY_KEY_S));
            if (!OUTPUT_INTENT_DICTIONARY_VALUE_GTS_PDFA1.equals(sValue)) {
                result.add(new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_S_VALUE_INVALID,
                        "The S entry of the OutputIntent isn't GTS_PDFA1"));
                continue;
            }

            // ---- OutputConditionIdentifier is a mandatory field
            String outputConditionIdentifier = dictionary
                    .getString(COSName.getPDFName(OUTPUT_INTENT_DICTIONARY_KEY_OUTPUT_CONDITION_IDENTIFIER));
            if (outputConditionIdentifier == null || "".equals(outputConditionIdentifier)) {
                result.add(new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
                        "The OutputIntentCondition is missing"));
                continue;
            }

            // ---- If OutputConditionIdentifier is "Custom" :
            // ---- DestOutputProfile and Info are mandatory
            // ---- DestOutputProfile must be a ICC Profile

            // ---- Because of PDF/A conforming file needs to specify the color
            // characteristics, the DestOutputProfile
            // is checked even if the OutputConditionIdentifier isn't "Custom"
            COSBase dop = dictionary
                    .getItem(COSName.getPDFName(OUTPUT_INTENT_DICTIONARY_KEY_DEST_OUTPUT_PROFILE));
            ValidationError valer = validateICCProfile(dop, cDoc, tmpDestOutputProfile, handler);
            if (valer != null) {
                result.add(valer);
                continue;
            }

            if (OUTPUT_INTENT_DICTIONARY_VALUE_OUTPUT_CONDITION_IDENTIFIER_CUSTOM
                    .equals(outputConditionIdentifier)) {
                String info = dictionary.getString(COSName.getPDFName(OUTPUT_INTENT_DICTIONARY_KEY_INFO));
                if (info == null || "".equals(info)) {
                    result.add(new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
                            "The Info entry of a OutputIntent dictionary is missing"));
                    continue;
                }
            }
        }
    }
    return result;
}

From source file:org.apache.fop.render.pdf.PageParentTreeFinderTestCase.java

License:Apache License

@Test
public void testGetPageParentTreeArray() throws IOException {
    File resource = new File(getClass().getResource(LINK).getFile());
    PDDocument doc = PDDocument.load(resource);
    PDPage srcPage = doc.getPage(0);//w  w  w  .j a  v  a  2 s  . com
    PageParentTreeFinder finder = new PageParentTreeFinder(srcPage);
    COSArray markedContentParents = finder.getPageParentTreeArray(doc);
    Assert.assertEquals(markedContentParents.size(), 3);
    COSObject firstObj = (COSObject) markedContentParents.get(0);
    COSObject secObj = (COSObject) markedContentParents.get(1);
    COSArray firstKids = (COSArray) firstObj.getDictionaryObject(COSName.K);
    COSDictionary firstKid = (COSDictionary) firstKids.get(0);
    int test = firstKid.getInt("MCID");
    int expected = 0;
    Assert.assertEquals(test, expected);
    COSDictionary firstKidBrother = (COSDictionary) firstKids.get(2);
    test = firstKidBrother.getInt("MCID");
    expected = 2;
    Assert.assertEquals(test, expected);
    COSArray secKidsArray = (COSArray) secObj.getDictionaryObject(COSName.K);
    COSDictionary secondKid = (COSDictionary) secKidsArray.get(0);
    test = secondKid.getInt("MCID");
    expected = 1;
    Assert.assertEquals(test, expected);
}