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.metadata;
018
019import com.itextpdf.text.pdf.PdfReader;
020import com.itextpdf.text.pdf.PdfStamper;
021import cz.hobrasoft.pdfmu.jackson.EmptyResult;
022import cz.hobrasoft.pdfmu.operation.Operation;
023import cz.hobrasoft.pdfmu.operation.OperationCommon;
024import cz.hobrasoft.pdfmu.operation.OperationException;
025import cz.hobrasoft.pdfmu.operation.args.InOutPdfArgs;
026import java.util.Arrays;
027import java.util.List;
028import java.util.Map;
029import java.util.logging.Logger;
030import net.sourceforge.argparse4j.inf.Namespace;
031import net.sourceforge.argparse4j.inf.Subparser;
032
033public class OperationMetadataSet extends OperationCommon {
034
035    private static final Logger logger = Logger.getLogger(OperationMetadataSet.class.getName());
036
037    private final MetadataParameters metadataParameters = new MetadataParameters();
038
039    private final InOutPdfArgs inout = new InOutPdfArgs();
040
041    @Override
042    public Subparser configureSubparser(Subparser subparser) {
043        String help = "Update PDF properties of a PDF document";
044
045        // Configure the subparser
046        subparser.help(help)
047                .description(help)
048                .defaultHelp(true);
049
050        inout.addArguments(subparser);
051        metadataParameters.addArguments(subparser);
052
053        return subparser;
054    }
055
056    @Override
057    public void execute(Namespace namespace) throws OperationException {
058        inout.setFromNamespace(namespace);
059        metadataParameters.setFromNamespace(namespace);
060        set(inout, metadataParameters);
061        writeResult(new EmptyResult());
062    }
063
064    private static void set(InOutPdfArgs inout, MetadataParameters metadataParameters) throws OperationException {
065        try {
066            inout.open();
067            PdfReader reader = inout.getPdfReader();
068            PdfStamper stp = inout.getPdfStamper();
069            set(reader, stp, metadataParameters);
070            inout.close(true);
071        } finally {
072            inout.close(false);
073        }
074    }
075
076    private static void set(PdfReader reader, PdfStamper stamper, MetadataParameters metadataParameters) {
077        Map<String, String> info = metadataParameters.getInfo(reader);
078        set(stamper, info);
079    }
080
081    private static final List<String> ignoredProperties
082            = Arrays.asList(new String[]{"Producer", "ModDate"});
083
084    public static void set(PdfStamper stp, Map<String, String> info) {
085        assert stp != null;
086        assert info != null;
087
088        for (String key : ignoredProperties) {
089            if (info.containsKey(key)) {
090                String value = info.get(key);
091                logger.warning(String.format("Warning: The property %s is set automatically. The value \"%s\" will be ignored.", key, value));
092            }
093        }
094
095        stp.setMoreInfo(info);
096        logger.info("PDF metadata have been set.");
097    }
098
099    private static Operation instance = null;
100
101    public static Operation getInstance() {
102        if (instance == null) {
103            instance = new OperationMetadataSet();
104        }
105        return instance;
106    }
107
108    private OperationMetadataSet() {
109        // Singleton
110    }
111
112}