| /* |
| * 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. |
| */ |
| |
| /* $Id$ */ |
| |
| package org.apache.fop.pdf; |
| |
| import java.text.MessageFormat; |
| |
| /** |
| * This class allows tracks the enabled PDF profiles (PDF/A and PDF/X) and provides methods to |
| * the libarary and its users to enable the generation of PDFs conforming to the enabled PDF |
| * profiles. |
| * <p> |
| * Some profile from PDF/X and PDF/A can be active simultaneously (example: PDF/A-1 and |
| * PDF/X-3:2003). |
| */ |
| public class PDFProfile { |
| |
| /** |
| * Indicates the PDF/A mode currently active. Defaults to "no restrictions", i.e. |
| * PDF/A not active. |
| */ |
| protected PDFAMode pdfAMode = PDFAMode.DISABLED; |
| |
| /** |
| * Indicates the PDF/X mode currently active. Defaults to "no restrictions", i.e. |
| * PDF/X not active. |
| */ |
| protected PDFXMode pdfXMode = PDFXMode.DISABLED; |
| |
| private PDFDocument doc; |
| |
| /** |
| * Main constructor |
| * @param doc the PDF document |
| */ |
| public PDFProfile(PDFDocument doc) { |
| this.doc = doc; |
| } |
| |
| /** |
| * Validates if the requested profile combination is compatible. |
| */ |
| protected void validateProfileCombination() { |
| if (pdfAMode != PDFAMode.DISABLED) { |
| if (pdfAMode == PDFAMode.PDFA_1A) { |
| throw new UnsupportedOperationException("PDF/A-1a is not implemented, yet"); |
| } |
| if (pdfAMode == PDFAMode.PDFA_1B) { |
| if (pdfXMode != PDFXMode.DISABLED && pdfXMode != PDFXMode.PDFX_3_2003) { |
| throw new PDFConformanceException( |
| pdfAMode + " and " + pdfXMode + " are not compatible!"); |
| } |
| } |
| } |
| } |
| |
| /** @return the PDFDocument this profile is attached to */ |
| public PDFDocument getDocument() { |
| return this.doc; |
| } |
| |
| /** @return the PDF/A mode */ |
| public PDFAMode getPDFAMode() { |
| return this.pdfAMode; |
| } |
| |
| /** @return true if any PDF/A mode is active */ |
| public boolean isPDFAActive() { |
| return getPDFAMode() != PDFAMode.DISABLED; |
| } |
| |
| /** |
| * Sets the PDF/A mode |
| * @param mode the PDF/A mode |
| */ |
| public void setPDFAMode(PDFAMode mode) { |
| if (mode == null) { |
| mode = PDFAMode.DISABLED; |
| } |
| this.pdfAMode = mode; |
| validateProfileCombination(); |
| } |
| |
| /** @return the PDF/X mode */ |
| public PDFXMode getPDFXMode() { |
| return this.pdfXMode; |
| } |
| |
| /** @return true if any PDF/X mode is active */ |
| public boolean isPDFXActive() { |
| return getPDFXMode() != PDFXMode.DISABLED; |
| } |
| |
| /** |
| * Sets the PDF/X mode |
| * @param mode the PDF/X mode |
| */ |
| public void setPDFXMode(PDFXMode mode) { |
| if (mode == null) { |
| mode = PDFXMode.DISABLED; |
| } |
| this.pdfXMode = mode; |
| validateProfileCombination(); |
| } |
| |
| /** {@inheritDoc} */ |
| public String toString() { |
| StringBuffer sb = new StringBuffer(); |
| if (isPDFAActive() && isPDFXActive()) { |
| sb.append("[").append(getPDFAMode()).append(",").append(getPDFXMode()).append("]"); |
| } else if (isPDFAActive()) { |
| sb.append(getPDFAMode()); |
| } else if (isPDFXActive()) { |
| sb.append(getPDFXMode()); |
| } else { |
| sb.append(super.toString()); |
| } |
| return sb.toString(); |
| } |
| |
| //---------=== Info and validation methods ===--------- |
| |
| private String format(String pattern, Object arg) { |
| return MessageFormat.format(pattern, new Object[] {arg}); |
| } |
| |
| /** Checks if encryption is allowed. */ |
| public void verifyEncryptionAllowed() { |
| final String err = "{0} doesn't allow encrypted PDFs"; |
| if (isPDFAActive()) { |
| throw new PDFConformanceException(format(err, getPDFAMode())); |
| } |
| if (isPDFXActive()) { |
| throw new PDFConformanceException(format(err, getPDFXMode())); |
| } |
| } |
| |
| /** Checks if PostScript XObjects are allowed. */ |
| public void verifyPSXObjectsAllowed() { |
| final String err = "PostScript XObjects are prohibited when {0}" |
| + " is active. Convert EPS graphics to another format."; |
| if (isPDFAActive()) { |
| throw new PDFConformanceException(format(err, getPDFAMode())); |
| } |
| if (isPDFXActive()) { |
| throw new PDFConformanceException(format(err, getPDFXMode())); |
| } |
| } |
| |
| /** |
| * Checks if the use of transparency is allowed. |
| * @param context Context information for the user to identify the problem spot |
| */ |
| public void verifyTransparencyAllowed(String context) { |
| final String err = "{0} does not allow the use of transparency. ({1})"; |
| if (isPDFAActive()) { |
| throw new PDFConformanceException(MessageFormat.format(err, |
| new Object[] {getPDFAMode(), context})); |
| } |
| if (isPDFXActive()) { |
| throw new PDFConformanceException(MessageFormat.format(err, |
| new Object[] {getPDFXMode(), context})); |
| } |
| } |
| |
| /** Checks if the right PDF version is set. */ |
| public void verifyPDFVersion() { |
| final String err = "PDF version must be 1.4 for {0}"; |
| if (getPDFAMode().isPDFA1LevelB() |
| && getDocument().getPDFVersion() != PDFDocument.PDF_VERSION_1_4) { |
| throw new PDFConformanceException(format(err, getPDFAMode())); |
| } |
| if (getPDFXMode() == PDFXMode.PDFX_3_2003 |
| && getDocument().getPDFVersion() != PDFDocument.PDF_VERSION_1_4) { |
| throw new PDFConformanceException(format(err, getPDFXMode())); |
| } |
| } |
| |
| /** @return true if the ID entry must be present in the trailer. */ |
| public boolean isIDEntryRequired() { |
| return isPDFAActive() || isPDFXActive(); |
| } |
| |
| /** @return true if all fonts need to be embedded. */ |
| public boolean isFontEmbeddingRequired() { |
| return isPDFAActive() || isPDFXActive(); |
| } |
| |
| /** Checks if a title may be absent. */ |
| public void verifyTitleAbsent() { |
| if (isPDFXActive()) { |
| final String err = "{0} requires the title to be set."; |
| throw new PDFConformanceException(format(err, getPDFXMode())); |
| } |
| } |
| |
| /** @return true if the ModDate Info entry must be present. */ |
| public boolean isModDateRequired() { |
| return getPDFXMode() == PDFXMode.PDFX_3_2003; |
| } |
| |
| /** @return true if the Trapped Info entry must be present. */ |
| public boolean isTrappedEntryRequired() { |
| return getPDFXMode() == PDFXMode.PDFX_3_2003; |
| } |
| |
| /** @return true if annotations are allowed */ |
| public boolean isAnnotationAllowed() { |
| return !isPDFXActive(); |
| } |
| |
| /** Checks if annotations are allowed. */ |
| public void verifyAnnotAllowed() { |
| if (!isAnnotationAllowed()) { |
| final String err = "{0} does not allow annotations inside the printable area."; |
| //Note: this rule is simplified. Refer to the standard for details. |
| throw new PDFConformanceException(format(err, getPDFXMode())); |
| } |
| } |
| |
| /** Checks if Actions are allowed. */ |
| public void verifyActionAllowed() { |
| if (isPDFXActive()) { |
| final String err = "{0} does not allow Actions."; |
| throw new PDFConformanceException(format(err, getPDFXMode())); |
| } |
| } |
| |
| } |