All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.verapdf.model.impl.pb.pd.PBoxPDDocument Maven / Gradle / Ivy

/**
 * This file is part of veraPDF PDF Box PDF/A Validation Model Implementation, a module of the veraPDF project.
 * Copyright (c) 2015, veraPDF Consortium 
 * All rights reserved.
 *
 * veraPDF PDF Box PDF/A Validation Model Implementation is free software: you can redistribute it and/or modify
 * it under the terms of either:
 *
 * The GNU General public license GPLv3+.
 * You should have received a copy of the GNU General Public License
 * along with veraPDF PDF Box PDF/A Validation Model Implementation as the LICENSE.GPL file in the root of the source
 * tree.  If not, see http://www.gnu.org/licenses/ or
 * https://www.gnu.org/licenses/gpl-3.0.en.html.
 *
 * The Mozilla Public License MPLv2+.
 * You should have received a copy of the Mozilla Public License along with
 * veraPDF PDF Box PDF/A Validation Model Implementation as the LICENSE.MPL file in the root of the source tree.
 * If a copy of the MPL was not distributed with this file, you can obtain one at
 * http://mozilla.org/MPL/2.0/.
 */
package org.verapdf.model.impl.pb.pd;

import java.util.logging.Logger;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.pdmodel.common.PDDestinationOrAction;
import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureTreeRoot;
import org.apache.pdfbox.pdmodel.graphics.optionalcontent.PDOptionalContentProperties;
import org.apache.pdfbox.pdmodel.interactive.action.PDDocumentCatalogAdditionalActions;
import org.verapdf.model.baselayer.Object;
import org.verapdf.model.coslayer.CosLang;
import org.verapdf.model.impl.pb.cos.PBCosLang;
import org.verapdf.model.impl.pb.pd.actions.PBoxPDAction;
import org.verapdf.model.impl.pb.pd.actions.PBoxPDCatalogAdditionalActions;
import org.verapdf.model.impl.pb.pd.signatures.PBoxPDPerms;
import org.verapdf.model.pdlayer.*;
import org.verapdf.model.tools.OutlinesHelper;
import org.verapdf.pdfa.flavours.PDFAFlavour;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.verapdf.model.impl.pb.pd.PBoxPDPage.SQUARE_ORIENTATION;

/**
 * High-level representation of pdf document.
 * Implemented by Apache PDFBox
 *
 * @author Evgeniy Muravitskiy
 */
public class PBoxPDDocument extends PBoxPDObject implements PDDocument {

	private static final Logger LOGGER = Logger.getLogger(PBoxPDDocument.class.getCanonicalName());

	/**
	 * Type name for {@code PBoxPDDocument}
	 */
	public static final String PD_DOCUMENT_TYPE = "PDDocument";

	/**
	 * Link name for pages
	 */
	public static final String PAGES = "pages";
	/**
	 * Link name for main metadata of document
	 */
	public static final String METADATA = "metadata";
	/**
	 * Link name for all output intents
	 */
	public static final String OUTPUT_INTENTS = "outputIntents";
	/**
	 * Link name for acro forms
	 */
	public static final String ACRO_FORMS = "AcroForm";
	/**
	 * Link name for additional actions of document
	 */
	public static final String ACTIONS = "AA";
	/**
	 * Link name for open action of document
	 */
	public static final String OPEN_ACTION = "OpenAction";
	public static final String OPEN_ACTION_DESTINATION = "OpenActionDestination";
	/**
	 * Link name for all outlines of document
	 */
	public static final String OUTLINES = "Outlines";
	/**
	 * Link name for annotations structure tree root of document
	 */
	public static final String STRUCTURE_TREE_ROOT = "StructTreeRoot";
	/**
	 * Link name for alternate presentation of names tree of document
	 */
	public static final String ALTERNATE_PRESENTATIONS = "AlternatePresentations";
	/**
	 * Link name for optional content properties of the document
	 */
	public static final String OC_PROPERTIES = "OCProperties";
	/**
	 * Name of link to Lang value from the document catalog dictionary
	 */
	public static final String LANG = "Lang";
	/**
	 * Name of link to Perms value
	 */
	public static final String PERMS = "Perms";

	private final PDDocumentCatalog catalog;
	private final PDFAFlavour flavour;
	private OutputIntents outputIntents = null;

	/**
	 * Default constructor
	 *
	 * @param document high level document representation
	 */
	public PBoxPDDocument(org.apache.pdfbox.pdmodel.PDDocument document, PDFAFlavour flavour) {
		super(document, PD_DOCUMENT_TYPE);
		this.catalog = this.document.getDocumentCatalog();
		this.flavour = flavour;
	}

	@Override
	public Boolean getcontainsAA() {
		return this.catalog != null && this.catalog.getCOSObject().containsKey(COSName.AA);
	}

	@Override
	public String getVersion() {
		return catalog.getVersion();
	}

	@Override
	public String getmostCommonOrientation() {
		List twoTheMostFrequent = getPages()
				.stream()
				.map(PDPage::getorientation)
				.collect(Collectors.groupingBy(a -> a, Collectors.counting()))
				.entrySet()
				.stream()
				.sorted(Map.Entry.comparingByValue().reversed())
				.limit(2)
				.map(Map.Entry::getKey)
				.collect(Collectors.toList());
		return SQUARE_ORIENTATION.equals(twoTheMostFrequent.get(0)) && twoTheMostFrequent.size() == 2 ? twoTheMostFrequent.get(1) : twoTheMostFrequent.get(0);
	}

	@Override
	public Boolean getcontainsXRefStream() {
		return false;
	}

	@Override
	public List getLinkedObjects(String link) {
		switch (link) {
			case OUTLINES:
				return this.getOutlines();
			case OPEN_ACTION:
				return this.getOpenAction();
			case OPEN_ACTION_DESTINATION:
				return Collections.emptyList();				
			case ACTIONS:
				return this.getActions();
			case PAGES:
				return this.getPages();
			case METADATA:
				return this.getMetadata();
			case OUTPUT_INTENTS:
				return this.getOutputIntents();
			case ACRO_FORMS:
				return this.getAcroForms();
			case STRUCTURE_TREE_ROOT:
				return this.getStructureTreeRoot();
			case OC_PROPERTIES:
				return this.getOCProperties();
			case LANG:
				return this.getLang();
			case PERMS:
				return this.getPerms();
			default:
				return super.getLinkedObjects(link);
		}
	}

	private List getOutputIntents() {
		if (this.outputIntents == null) {
			this.outputIntents = parseOutputIntents();
		}
		if (this.outputIntents != null) {
			List array = new ArrayList<>(MAX_NUMBER_OF_ELEMENTS);
			array.add(this.outputIntents);
			return array;
		}
		return Collections.emptyList();
	}

	@Override
	public String getoutputColorSpace() {
		if (this.outputIntents == null) {
			this.outputIntents = parseOutputIntents();
		}
		return this.outputIntents != null ? ((PBoxOutputIntents)this.outputIntents).getColorSpace() : null;
	}

	private OutputIntents parseOutputIntents() {
		if (this.catalog != null) {
			List outInts =
					this.catalog.getOutputIntents();
			if (outInts.size() > 0) {
				return new PBoxOutputIntents(outInts, document, flavour);
			}
		}
		return null;
	}

	private List getOutlines() {
		return OutlinesHelper.getOutlines(this.catalog);
	}

	private List getOpenAction() {
		if (this.catalog != null) {
			try {
				PDDestinationOrAction openAction = this.catalog.getOpenAction();
				if (openAction instanceof org.apache.pdfbox.pdmodel.interactive.action.PDAction) {
					List actions = new ArrayList<>(MAX_NUMBER_OF_ELEMENTS);
					PDAction action = PBoxPDAction.getAction((org.apache.pdfbox.pdmodel.interactive.action.PDAction)openAction);
					if (action != null) {
						actions.add(action);
						return Collections.unmodifiableList(actions);
					}
				}
			} catch (IOException e) {
				LOGGER.log(java.util.logging.Level.INFO,
						"Problems with open action obtaining. " + e.getMessage());
			}
		}
		return Collections.emptyList();
	}

	private List getActions() {
		PDDocumentCatalogAdditionalActions pbActions = this.getAdditionalAction();
		if (pbActions != null && pbActions.getCOSObject().size() != 0) {
			List actions = new ArrayList<>(MAX_NUMBER_OF_ELEMENTS);
			actions.add(new PBoxPDCatalogAdditionalActions(pbActions));
			return Collections.unmodifiableList(actions);
		}
		return Collections.emptyList();
	}

	private PDDocumentCatalogAdditionalActions getAdditionalAction() {
		if (this.catalog != null) {
			COSDictionary catalogLocal = this.catalog.getCOSObject();
			COSBase aaDictionary = catalogLocal.getDictionaryObject(COSName.AA);
			if (aaDictionary instanceof COSDictionary) {
				return new PDDocumentCatalogAdditionalActions((COSDictionary) aaDictionary);
			}
		}
		return null;
	}

	private List getPages() {
		PDPageTree pageTree = this.document.getPages();
		List pages = new ArrayList<>(pageTree.getCount());
		for (org.apache.pdfbox.pdmodel.PDPage page : pageTree) {
			pages.add(new PBoxPDPage(page, this.document, this.flavour));
		}
		return Collections.unmodifiableList(pages);
	}

	private List getMetadata() {
		if (this.catalog != null) {
			org.apache.pdfbox.pdmodel.common.PDMetadata meta = this.catalog.getMetadata();
			if (meta != null && PBoxPDMetadata.isMetadataObject(meta.getCOSObject())) {
				List metadata = new ArrayList<>(MAX_NUMBER_OF_ELEMENTS);
				metadata.add(new PBoxPDMetadata(meta, Boolean.TRUE, this.document, this.flavour));
				return Collections.unmodifiableList(metadata);
			}
		}
		return Collections.emptyList();
	}

	private List getAcroForms() {
		if (this.catalog != null) {
			org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm form =
					this.catalog.getAcroForm();
			if (form != null) {
				List forms = new ArrayList<>(MAX_NUMBER_OF_ELEMENTS);
				forms.add(new PBoxPDAcroForm(form, this.document, this.flavour));
				return Collections.unmodifiableList(forms);
			}
		}
		return Collections.emptyList();
	}

	private List getStructureTreeRoot() {
		if (this.catalog != null) {
			PDStructureTreeRoot root = this.catalog.getStructureTreeRoot();
			if (root != null) {
				List treeRoot = new ArrayList<>(MAX_NUMBER_OF_ELEMENTS);
				treeRoot.add(new PBoxPDStructTreeRoot(root, this.flavour));
				return Collections.unmodifiableList(treeRoot);
			}
		}
		return Collections.emptyList();
	}

	private List getPerms() {
		if (this.catalog != null) {
			COSDictionary perms = (COSDictionary)
					this.catalog.getCOSObject().getDictionaryObject(COSName.PERMS);
			if (perms != null) {
				List list = new ArrayList<>(MAX_NUMBER_OF_ELEMENTS);
				list.add(new PBoxPDPerms(perms));
				return Collections.unmodifiableList(list);
			}
		}
		return Collections.emptyList();
	}

	@Override
	public Boolean getcontainsAlternatePresentations() {
		if (this.catalog != null) {
			COSDictionary rawCatalog = this.catalog.getCOSObject();

			COSDictionary namesDictionary = (COSDictionary) rawCatalog.getDictionaryObject(COSName.NAMES);
			if (namesDictionary != null) {

				COSBase alternatePresentations = namesDictionary.getDictionaryObject(COSName.getPDFName(ALTERNATE_PRESENTATIONS));

				if (alternatePresentations != null) {
					return Boolean.TRUE;
				}
			}
		}
		return Boolean.FALSE;
	}

	private List getOCProperties() {
		if (this.catalog != null) {
			PDOptionalContentProperties pBoxOCProperties = this.catalog.getOCProperties();
			if (pBoxOCProperties != null) {
				List result = new ArrayList<>();

				PDOCProperties ocProperties = new PBoxPDOCProperties(pBoxOCProperties);
				result.add(ocProperties);

				return result;
			}
		}
		return Collections.emptyList();
	}

	private List getLang() {
		if (this.catalog != null) {
			COSBase baseLang = catalog.getCOSObject().getDictionaryObject(COSName.LANG);
			if (baseLang instanceof COSString) {
				List list = new ArrayList<>(MAX_NUMBER_OF_ELEMENTS);
				list.add(new PBCosLang((COSString) baseLang));
				return Collections.unmodifiableList(list);
			}
		}
		return Collections.emptyList();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy