org.qxsched.doc.afp.util.AfpDump.java Source code

Java tutorial

Introduction

Here is the source code for org.qxsched.doc.afp.util.AfpDump.java

Source

package org.qxsched.doc.afp.util;

import jargs.gnu.CmdLineParser;
import jargs.gnu.CmdLineParser.IllegalOptionValueException;
import jargs.gnu.CmdLineParser.UnknownOptionException;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.qxsched.doc.afp.AfpException;
import org.qxsched.doc.afp.AfpFactory;
import org.qxsched.doc.afp.AfpReadWriteProperties;
import org.qxsched.doc.afp.AfpRecord;
import org.qxsched.doc.afp.AfpRecordGrouper;
import org.qxsched.doc.afp.AfpStructuredFieldDefinitions;
import org.qxsched.doc.afp.util.AfpDump.Options.OptionsException;

/*
 * 
 * Copyright 2009, 2010, 2011 Vincenzo Zocca
 * 
 * This file is part of Java library org.qxsched.doc.afp.
 *
 * Java library org.qxsched.doc.afp is free software: you can redistribute
 * it and/or modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Java library org.qxsched.doc.afp is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Java library org.qxsched.doc.afp.
 * If not, see <http://www.gnu.org/licenses/>.
 * 
 */

/**
 * Class {@link AfpDump} is a simple utility that prints the contents of an AFP
 * file in human readable format. It is implemented using classes in package
 * {@link org.qxsched.doc.afp}.
 * 
 * @author Vincenzo Zocca
 * 
 */
public class AfpDump {

    // Private class to parse arguments
    protected class Options {

        // Private class for illegal options.
        protected class OptionsException extends Exception {

            private static final long serialVersionUID = 5011257380515029864L;

            public OptionsException() {
                super();
            }

            public OptionsException(String message) {
                super(message);
            }

            public OptionsException(String message, Throwable cause) {
                super(message, cause);
            }

            public OptionsException(Throwable cause) {
                super(cause);
            }

        }

        // The command line parser
        private CmdLineParser cmdLineParser = null;

        // Option -c
        private Map<Integer, Object> convert_specific;
        private CmdLineParser.Option convert_specific_opt;

        // Option --group-records
        private boolean group_records = false;
        private CmdLineParser.Option group_records_opt;

        // Option -h
        private boolean help = false;
        private CmdLineParser.Option help_opt;

        // Option --md-thold
        private Integer md_thold;
        private CmdLineParser.Option md_thold_opt;

        // Option -o
        private String out_file;
        private CmdLineParser.Option out_file_opt;

        // Option --out-cs
        private String out_file_cs;
        private CmdLineParser.Option out_file_cs_opt;

        // Value remaining argument
        private String remainingArg;

        protected Options(String[] args)
                throws IllegalOptionValueException, UnknownOptionException, OptionsException, AfpException {

            // Initialize
            initOptions();

            // Parse the options
            parseOptions(args);
        }

        /**
         * Returns a map of records that must be converted to specific
         * implementations. Keys are record codes .
         * 
         * @return a map of records that must be converted to specific
         *         implementations.
         */
        public Map<Integer, Object> getConvert_specific() {
            return convert_specific;
        }

        /**
         * Returns the message digest threshold.
         * 
         * @return the message digest threshold.
         */
        protected Integer getMd_thold() {
            return md_thold;
        }

        /**
         * Returns the output file.
         * 
         * @return the output file.
         */
        protected String getOutFile() {
            return out_file;
        }

        /**
         * Returns the character set for the output file.
         * 
         * @return the character set for the output file.
         */
        protected String getOutFileCs() {
            return out_file_cs;
        }

        /**
         * Returns the remaining argument.
         * 
         * @return the remaining argument.
         */
        protected String getRemainingArg() {
            return remainingArg;
        }

        private void initOptions() {

            // Return if cmdLineParser is defined
            if (cmdLineParser != null)
                return;

            // Create the command line parser
            cmdLineParser = new CmdLineParser();

            // Convert specific
            if (OPT_CONVERT_SPECIFIC_CHR == null) {
                convert_specific_opt = new CmdLineParser.Option.StringOption(OPT_CONVERT_SPECIFIC_STR);
            } else {
                convert_specific_opt = new CmdLineParser.Option.StringOption(OPT_CONVERT_SPECIFIC_CHR.charValue(),
                        OPT_CONVERT_SPECIFIC_STR);
            }
            cmdLineParser.addOption(convert_specific_opt);

            // Group records
            if (OPT_GROUP_RECORDS_CHR == null) {
                group_records_opt = new CmdLineParser.Option.BooleanOption(OPT_GROUP_RECORDS_STR);
            } else {
                group_records_opt = new CmdLineParser.Option.BooleanOption(OPT_GROUP_RECORDS_CHR.charValue(),
                        OPT_GROUP_RECORDS_STR);
            }
            cmdLineParser.addOption(group_records_opt);

            // Help
            if (OPT_HELP_CHR == null) {
                help_opt = new CmdLineParser.Option.BooleanOption(OPT_HELP_STR);
            } else {
                help_opt = new CmdLineParser.Option.BooleanOption(OPT_HELP_CHR.charValue(), OPT_HELP_STR);
            }
            cmdLineParser.addOption(help_opt);

            // Message digest threshold
            if (OPT_MD_THOLD_CHR == null) {
                md_thold_opt = new CmdLineParser.Option.IntegerOption(OPT_MD_THOLD_STR);
            } else {
                md_thold_opt = new CmdLineParser.Option.IntegerOption(OPT_MD_THOLD_CHR.charValue(),
                        OPT_MD_THOLD_STR);
            }
            cmdLineParser.addOption(md_thold_opt);

            // Out file
            if (OPT_OUT_FILE_CHR == null) {
                out_file_opt = new CmdLineParser.Option.StringOption(OPT_OUT_FILE_STR);
            } else {
                out_file_opt = new CmdLineParser.Option.StringOption(OPT_OUT_FILE_CHR.charValue(),
                        OPT_OUT_FILE_STR);
            }
            cmdLineParser.addOption(out_file_opt);

            // Out file charset
            if (OPT_OUT_FILE_CS_CHR == null) {
                out_file_cs_opt = new CmdLineParser.Option.StringOption(OPT_OUT_FILE_CS_STR);
            } else {
                out_file_cs_opt = new CmdLineParser.Option.StringOption(OPT_OUT_FILE_CS_CHR.charValue(),
                        OPT_OUT_FILE_CS_STR);
            }
            cmdLineParser.addOption(out_file_cs_opt);

        }

        /**
         * Returns <code>true</code> if the group records option was supplied.
         * 
         * @return <code>true</code> if the group records option was supplied.
         */
        public boolean isGroup_records() {
            return group_records;
        }

        /**
         * Returns <code>true</code> if the help option was supplied.
         * 
         * @return <code>true</code> if the help record options was supplied.
         */
        public boolean isHelp() {
            return help;
        }

        // Parse options
        private void parseOptions(String args[])
                throws IllegalOptionValueException, UnknownOptionException, OptionsException, AfpException {

            // Parse the command line
            cmdLineParser.parse(args);

            // Option -c
            String valS = (String) cmdLineParser.getOptionValue(convert_specific_opt);
            if (valS != null) {

                // Instantiate convert specific
                convert_specific = new HashMap<Integer, Object>();

                // Split value
                String[] valArr = valS.split("\\W+");

                // Get AFP structured field definitions
                AfpStructuredFieldDefinitions defs = AfpStructuredFieldDefinitions.instance();

                // Loop through elements
                StringBuffer error = new StringBuffer();
                for (int i = 0; i < valArr.length; i++) {

                    // Ignore empty
                    if (valArr[i].equals("")) {
                        continue;
                    }

                    // Get code for abbreviated type
                    Integer code = defs.getCode(valArr[i]);
                    if (code == null) {
                        error.append("Cannot obtain record code for '");
                        error.append(valArr[i]);
                        error.append("'. ");
                    }

                    // Set convert specific
                    convert_specific.put(code, valArr[i]);

                }
                if (error.length() > 0) {
                    throw new OptionsException(error.toString());
                }
            }

            // Option --group-records
            Boolean boolVal = (Boolean) cmdLineParser.getOptionValue(group_records_opt);
            if (boolVal != null) {
                group_records = boolVal.booleanValue();
            }

            // Option -h
            boolVal = (Boolean) cmdLineParser.getOptionValue(help_opt);
            if (boolVal != null) {
                help = boolVal.booleanValue();
            }

            // Option --md-thold
            md_thold = (Integer) cmdLineParser.getOptionValue(md_thold_opt);

            // Option -o
            out_file = (String) cmdLineParser.getOptionValue(out_file_opt);

            // Option --out-cs
            out_file_cs = (String) cmdLineParser.getOptionValue(out_file_cs_opt);

            // Remaining arguments
            String[] remainingArgs = cmdLineParser.getRemainingArgs();
            switch (remainingArgs.length) {
            case 0:
                break;

            case 1:
                remainingArg = remainingArgs[0];
                break;

            default:
                throw new OptionsException("Zero or one file name can be specified after the options.");
            }
        }
    }

    // Logger
    private static Logger LOG = Logger.getLogger(AfpDump.class);

    private static final Character OPT_CONVERT_SPECIFIC_CHR = new Character('c');
    private static final String OPT_CONVERT_SPECIFIC_STR = "convert-specific";

    private static final Character OPT_GROUP_RECORDS_CHR = new Character('g');
    private static final String OPT_GROUP_RECORDS_STR = "group-records";

    private static final Character OPT_HELP_CHR = new Character('h');
    private static final String OPT_HELP_STR = "help";

    private static final Character OPT_MD_THOLD_CHR = null;
    private static final String OPT_MD_THOLD_STR = "md-thold";

    private static final Character OPT_OUT_FILE_CHR = new Character('o');
    private static final String OPT_OUT_FILE_STR = "out";

    private static final Character OPT_OUT_FILE_CS_CHR = null;
    private static final String OPT_OUT_FILE_CS_STR = "out-cs";

    public static void main(String[] arg) {

        try {

            // Instantiate
            AfpDump afpDump = new AfpDump(arg);

            // Run
            afpDump.run();

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        // Exit OK
        System.exit(0);
    }

    protected static String usage() {

        // String buffer
        StringBuffer sb = new StringBuffer();

        // Class
        sb.append(AfpDump.class.getName());
        sb.append(" \\");
        sb.append(System.getProperty("line.separator"));

        // OPT_CONVERT_SPECIFIC
        sb.append("\t");
        sb.append("[");
        if (OPT_CONVERT_SPECIFIC_CHR != null) {
            sb.append("-");
            sb.append(OPT_CONVERT_SPECIFIC_CHR);
            sb.append("|");
        }
        sb.append("--");
        sb.append(OPT_CONVERT_SPECIFIC_STR);
        sb.append(" [tle...]]");
        sb.append(" \\");
        sb.append(System.getProperty("line.separator"));

        // OPT_GROUP_RECORDS
        sb.append("\t");
        sb.append("[");
        if (OPT_GROUP_RECORDS_CHR != null) {
            sb.append("-");
            sb.append(OPT_GROUP_RECORDS_CHR);
            sb.append("|");
        }
        sb.append("--");
        sb.append(OPT_GROUP_RECORDS_STR);
        sb.append("]");
        sb.append(" \\");
        sb.append(System.getProperty("line.separator"));

        // OPT_HELP
        sb.append("\t");
        sb.append("[");
        if (OPT_HELP_CHR != null) {
            sb.append("-");
            sb.append(OPT_HELP_CHR);
            sb.append("|");
        }
        sb.append("--");
        sb.append(OPT_HELP_STR);
        sb.append("]");
        sb.append(" \\");
        sb.append(System.getProperty("line.separator"));

        // OPT_MD_THOLD
        sb.append("\t");
        sb.append("[");
        if (OPT_MD_THOLD_CHR != null) {
            sb.append("-");
            sb.append(OPT_MD_THOLD_CHR);
            sb.append("|");
        }
        sb.append("--");
        sb.append(OPT_MD_THOLD_STR);
        sb.append("]");
        sb.append(" \\");
        sb.append(System.getProperty("line.separator"));

        // OPT_OUT_FILE
        sb.append("\t");
        sb.append("[");
        if (OPT_OUT_FILE_CHR != null) {
            sb.append("-");
            sb.append(OPT_OUT_FILE_CHR);
            sb.append("|");
        }
        sb.append("--");
        sb.append(OPT_OUT_FILE_STR);
        sb.append(" <out-file>]");
        sb.append(" \\");
        sb.append(System.getProperty("line.separator"));

        // OPT_OUT_FILE_CS
        sb.append("\t");
        sb.append("[");
        if (OPT_OUT_FILE_CS_CHR != null) {
            sb.append("-");
            sb.append(OPT_OUT_FILE_CS_CHR);
            sb.append("|");
        }
        sb.append("--");
        sb.append(OPT_OUT_FILE_CS_STR);
        sb.append(" <out-file-charset>]");
        sb.append(" \\");
        sb.append(System.getProperty("line.separator"));

        // In-File
        sb.append("\t[in-file]");
        sb.append(System.getProperty("line.separator"));

        // Return
        return sb.toString();
    }

    // AFP read/write properties
    private AfpReadWriteProperties arwProps;

    // Input file
    private InputStream in;

    // Options
    private Options opts;

    // Output file
    private BufferedWriter out;

    public AfpDump(String[] args)
            throws IllegalOptionValueException, UnknownOptionException, OptionsException, AfpException {

        // Make options
        opts = this.new Options(args);

        // Make AFP read/write props
        makeAfpReadWriteProperties();
    }

    private void filesClose() throws IOException {
        in.close();
        out.close();
    }

    private void filesOpen() throws IOException {

        // Open input file for reading
        if (opts.getRemainingArg() == null) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Using STDIN as input");
            }
            in = new BufferedInputStream(System.in);
        } else {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Using " + opts.getRemainingArg() + " as input");
            }
            in = new BufferedInputStream(new FileInputStream(opts.getRemainingArg()));
        }

        // Open output file for writing
        OutputStream os = null;
        try {
            if (opts.getOutFile() == null) {
                os = new BufferedOutputStream(System.out);
            } else {
                os = new BufferedOutputStream(new FileOutputStream(opts.getOutFile()));
            }
        } catch (IOException e) {
            in.close();
            throw e;
        }
        String cs = opts.getOutFileCs();
        if (cs == null) {
            out = new BufferedWriter(new OutputStreamWriter(new BufferedOutputStream(os)));
        } else {
            out = new BufferedWriter(new OutputStreamWriter(new BufferedOutputStream(os), cs));
        }
    }

    private void makeAfpReadWriteProperties() {

        // Get default AFP read/write properties
        arwProps = new AfpReadWriteProperties();

        // Convert specific
        if (opts.getConvert_specific() != null) {

            // Clear current settings
            arwProps.setConvertSpecificNone();

            // Add codes
            Map<Integer, Object> convert_specific = opts.getConvert_specific();
            for (Integer code : convert_specific.keySet()) {
                arwProps.setConvertSpecific(code);
            }
        }

        // Message digest threshold
        if (opts.getMd_thold() != null) {
            arwProps.setMessageDigestThreshold(opts.getMd_thold().intValue());
        }
    }

    public void run() throws AfpException, IOException {

        // Usage
        if (opts.isHelp()) {
            System.err.print(usage());
            return;
        }

        // Open files
        filesOpen();

        try {

            // Create AfpFactory
            AfpFactory fact = AfpFactory.createAfpFactory();
            fact.setAfpReadWriteProperties(arwProps);

            // Set input stream
            fact.setInputStream(in);

            if (opts.isGroup_records()) {

                AfpRecordGrouper grouper = new AfpRecordGrouper(fact);

                // Read input until finished
                for (AfpRecord afpRecord = grouper.getAfpRecord(); afpRecord != null; afpRecord = grouper
                        .getAfpRecord()) {

                    // Write record
                    LOG.debug("afpRecord: " + afpRecord);
                    afpRecord.write(out, arwProps, 0);

                }

            } else {

                // Read input until finished
                while (in.available() > 0) {

                    // Read record
                    AfpRecord rec = fact.createAfpRecord();

                    // Write record
                    rec.write(out, arwProps, 0);
                }
            }
        } finally {
            // Close files
            filesClose();
        }
    }

    public static void dumpData(BufferedWriter out, AfpReadWriteProperties props, String label, String prefix,
            byte[] data) throws IOException {

        // Loop
        for (int i = 0; i < data.length;) {

            int iStart = i;
            out.write(prefix);
            out.write("    ");
            out.write(label);

            for (int j = i; j < data.length && j < iStart + 16; j++) {
                i++;

                int val = data[j] & 0xff;
                out.write(StringUtils.leftPad(Integer.toString(val, 16).toLowerCase(), 2, '0'));
                out.write(" ");

            }
            out.newLine();
        }
    }

    public static void dumpData(StringBuffer sb, AfpReadWriteProperties props, String label, String prefix,
            byte[] data, boolean doLastNl) {

        // Loop
        for (int i = 0; i < data.length;) {

            int iStart = i;
            sb.append(prefix);
            sb.append("    ");
            sb.append(label);

            for (int j = i; j < data.length && j < iStart + 16; j++) {
                i++;

                int val = data[j] & 0xff;
                sb.append(StringUtils.leftPad(Integer.toString(val, 16).toLowerCase(), 2, '0'));
                sb.append(" ");

            }
            if (doLastNl) {
                sb.append(System.getProperty("line.separator"));
            }
        }
    }

    public static String dumpData(AfpReadWriteProperties props, String label, String prefix, byte[] data,
            boolean doLastNl) {
        StringBuffer sb = new StringBuffer();
        dumpData(sb, props, label, prefix, data, doLastNl);
        return sb.toString();
    }
}