001/* 
002 * Copyright (C) 2016 Hobrasoft s.r.o.
003 *
004 * This program is free software: you can redistribute it and/or modify
005 * it under the terms of the GNU Affero General Public License as published by
006 * the Free Software Foundation, either version 3 of the License, or
007 * (at your option) any later version.
008 *
009 * This program is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU Affero General Public License for more details.
013 *
014 * You should have received a copy of the GNU Affero General Public License
015 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
016 */
017package cz.hobrasoft.pdfmu.operation.version;
018
019import com.itextpdf.text.pdf.PdfReader;
020import cz.hobrasoft.pdfmu.jackson.VersionSet;
021import cz.hobrasoft.pdfmu.operation.Operation;
022import cz.hobrasoft.pdfmu.operation.OperationCommon;
023import cz.hobrasoft.pdfmu.operation.OperationException;
024import cz.hobrasoft.pdfmu.operation.args.InOutPdfArgs;
025import cz.hobrasoft.pdfmu.operation.args.InPdfArgs;
026import cz.hobrasoft.pdfmu.operation.args.OutPdfArgs;
027import java.util.logging.Logger;
028import net.sourceforge.argparse4j.impl.Arguments;
029import net.sourceforge.argparse4j.inf.Namespace;
030import net.sourceforge.argparse4j.inf.Subparser;
031
032/**
033 * Sets the PDF version of a PDF document
034 *
035 * @author <a href="mailto:filip.bartek@hobrasoft.cz">Filip Bartek</a>
036 */
037public class OperationVersionSet extends OperationCommon {
038
039    private static final Logger logger = Logger.getLogger(OperationVersionSet.class.getName());
040
041    private final InOutPdfArgs inout = new InOutPdfArgs(false);
042
043    @Override
044    public Subparser configureSubparser(Subparser subparser) {
045        String help = "Set PDF version of a PDF document";
046        String description = help + "\nIf there are signatures in the document, this operation invalidates them.";
047
048        // Configure the subparser
049        subparser.help(help)
050                .description(description)
051                .defaultHelp(true);
052
053        inout.addArguments(subparser);
054
055        String metavarVersion = "VERSION";
056        subparser.addArgument("-v", "--version")
057                .help(String.format("set PDF version to %s", metavarVersion))
058                .metavar(metavarVersion)
059                .type(PdfVersion.class)
060                .setDefault(new PdfVersion("1.6"));
061
062        subparser.addArgument("--only-if-lower")
063                .help(String.format("only set version if the current version is lower than %s", metavarVersion))
064                .type(boolean.class)
065                .action(Arguments.storeTrue());
066
067        return subparser;
068    }
069
070    @Override
071    public void execute(Namespace namespace) throws OperationException {
072        inout.setFromNamespace(namespace);
073        PdfVersion outVersion = namespace.get("version");
074        boolean onlyIfLower = namespace.get("only_if_lower");
075
076        VersionSet result = execute(inout, outVersion, onlyIfLower);
077
078        writeResult(result);
079    }
080
081    private static VersionSet execute(InOutPdfArgs inout, PdfVersion outVersion, boolean onlyIfLower) throws OperationException {
082        InPdfArgs in = inout.getIn();
083        OutPdfArgs out = inout.getOut();
084
085        return execute(in, out, outVersion, onlyIfLower);
086    }
087
088    private static VersionSet execute(InPdfArgs in, OutPdfArgs out, PdfVersion outVersion, boolean onlyIfLower) throws OperationException {
089        try { // in
090            in.open();
091            PdfReader pdfReader = in.getPdfReader();
092
093            // Fetch the PDF version of the input PDF document
094            PdfVersion inVersion = new PdfVersion(pdfReader.getPdfVersion());
095            logger.info(String.format("Input PDF document version: %s", inVersion));
096
097            // Commence to set the PDF version of the output PDF document
098            // Determine the desired PDF version
099            assert outVersion != null; // The argument "version" has a default value
100            logger.info(String.format("Desired output PDF version: %s", outVersion));
101
102            boolean set = true;
103            if (outVersion.compareTo(inVersion) <= 0) {
104                // The desired version is lower than the current version.
105                if (onlyIfLower) {
106                    set = false;
107                    logger.info("The input PDF version is not lower than the desired version. No modification will be performed.");
108                } else {
109                    logger.warning("Setting the PDF version to a lower value.");
110                }
111            }
112
113            if (set) {
114                try { // out
115                    out.open(pdfReader, false, outVersion.toChar());
116                    out.close(true);
117                } finally {
118                    out.close(false);
119                }
120            }
121
122            return new VersionSet(inVersion.toString(), outVersion.toString(), set);
123        } finally {
124            in.close();
125        }
126    }
127
128    private static Operation instance = null;
129
130    public static Operation getInstance() {
131        if (instance == null) {
132            instance = new OperationVersionSet();
133        }
134        return instance;
135    }
136
137    private OperationVersionSet() {
138        // Singleton
139    }
140
141}